2011-12-19 10 views
6

Po pierwsze, muszę powiedzieć, że wiem, że generalnie nie jest dobrym pomysłem korzystanie ze specyfiki F # podczas integracji z innymi językami w .NET.F #, serializowanie dyskryminowanych związków z wartościami bez danych

Mój problem polega na tym, że nie rozumiem, jak utworzyć odniesienie do usługi, która zawiera metody prezentujące dyskryminowane związki.

mam podstaw, że idzie trochę coś takiego:

type TelephonyProductActivationData = 
    | MobileUseNextIcc 
    | Mobile of decimal 
    | MobileBroadbandUseNextIcc 
    | MobileBroadband of decimal 
    | Fixed 
    | Voip of int16 * int16 
    static member KnownTypes() = 
     typeof<TelephonyProductActivationData>.GetNestedTypes(BindingFlags.Public ||| BindingFlags.NonPublic) |> Array.filter FSharpType.IsUnion 

Jeśli używasz F # interaktywne najpierw utworzyć typ:

type TelephonyProductActivationData = 
    | MobileUseNextIcc of unit 
    | Mobile of decimal<Icc> 
    | MobileBroadbandUseNextIcc of unit 
    | MobileBroadband of decimal<Icc> 
    | Fixed of unit 
    | Voip of BoxNr * int16<BoxPort>;; 

I wykonać fragment kodu knowntypes (nieznacznie zmodyfikowane):

(typeof<TelephonyProductActivationData>.GetNestedTypes(System.Reflection.BindingFlags.Public ||| System.Reflection.BindingFlags.NonPublic) |> Array.filter Microsoft.FSharp.Reflection.FSharpType.IsUnion) |> Array.map (fun x -> x.FullName);; 

wyświetli się następujący wynik:

val it : string [] = 
    [|"FSI_0047+TelephonyProductActivationData+Mobile"; 
    "FSI_0047+TelephonyProductActivationData+MobileBroadband"; 
    "FSI_0047+TelephonyProductActivationData+Voip"|] 

Zauważ, że wartości, które nie mają powiązanych z nimi danych, zniknęły. Oznacza to, że żadne rodzaje nie będą tworzone podczas kompilowania tego dyskryminowanego związku. Przy wykonywaniu tego oświadczenia w F # interaktywne:

typeof<TelephonyProductActivationData>.GetProperties() |> Array.map (fun x -> (x.Name));; 

zobaczymy co stały się one:

val it : string [] = 
    [|"Tag"; "IsVoip"; "Fixed"; "IsFixed"; "IsMobileBroadband"; 
    "MobileBroadbandUseNextIcc"; "IsMobileBroadbandUseNextIcc"; "IsMobile"; 
    "MobileUseNextIcc"; "IsMobileUseNextIcc"|] 

Jak widać wartości bez dane powiązane z nimi stały właściwości. Teraz mogę pokazać ci prawdziwy problem. Podczas tworzenia odniesienia serwis do usługi z tej metody wszystko mam to:

[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] 
[System.Runtime.Serialization.DataContractAttribute(Name="ActivationModel.TelephonyProductActivationData", Namespace="http://schemas.datacontract.org/2004/07/Svea.Inri.Data")] 
[System.SerializableAttribute()] 
[System.Runtime.Serialization.KnownTypeAttribute(typeof(ConsoleApplication1.ServiceReference1.ActivationModelTelephonyProductActivationData.Mobile))] 
[System.Runtime.Serialization.KnownTypeAttribute(typeof(ConsoleApplication1.ServiceReference1.ActivationModelTelephonyProductActivationData.MobileBroadband))] 
[System.Runtime.Serialization.KnownTypeAttribute(typeof(ConsoleApplication1.ServiceReference1.ActivationModelTelephonyProductActivationData.Voip))] 
public partial class ActivationModelTelephonyProductActivationData : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged { 

    [System.NonSerializedAttribute()] 
    private System.Runtime.Serialization.ExtensionDataObject extensionDataField; 

    private int _tagField; 

    [global::System.ComponentModel.BrowsableAttribute(false)] 
    public System.Runtime.Serialization.ExtensionDataObject ExtensionData { 
     get { 
      return this.extensionDataField; 
     } 
     set { 
      this.extensionDataField = value; 
     } 
    } 

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)] 
    public int _tag { 
     get { 
      return this._tagField; 
     } 
     set { 
      if ((this._tagField.Equals(value) != true)) { 
       this._tagField = value; 
       this.RaisePropertyChanged("_tag"); 
      } 
     } 
    } 

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string propertyName) { 
     System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged; 
     if ((propertyChanged != null)) { 
      propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] 
    [System.Runtime.Serialization.DataContractAttribute(Name="ActivationModel.TelephonyProductActivationData.Mobile", Namespace="http://schemas.datacontract.org/2004/07/Svea.Inri.Data")] 
    [System.SerializableAttribute()] 
    public partial class Mobile : ConsoleApplication1.ServiceReference1.ActivationModelTelephonyProductActivationData { 

     private decimal itemField; 

     [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)] 
     public decimal item { 
      get { 
       return this.itemField; 
      } 
      set { 
       if ((this.itemField.Equals(value) != true)) { 
        this.itemField = value; 
        this.RaisePropertyChanged("item"); 
       } 
      } 
     } 
    } 

    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] 
    [System.Runtime.Serialization.DataContractAttribute(Name="ActivationModel.TelephonyProductActivationData.MobileBroadband", Namespace="http://schemas.datacontract.org/2004/07/Svea.Inri.Data")] 
    [System.SerializableAttribute()] 
    public partial class MobileBroadband : ConsoleApplication1.ServiceReference1.ActivationModelTelephonyProductActivationData { 

     private decimal itemField; 

     [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)] 
     public decimal item { 
      get { 
       return this.itemField; 
      } 
      set { 
       if ((this.itemField.Equals(value) != true)) { 
        this.itemField = value; 
        this.RaisePropertyChanged("item"); 
       } 
      } 
     } 
    } 

    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] 
    [System.Runtime.Serialization.DataContractAttribute(Name="ActivationModel.TelephonyProductActivationData.Voip", Namespace="http://schemas.datacontract.org/2004/07/Svea.Inri.Data")] 
    [System.SerializableAttribute()] 
    public partial class Voip : ConsoleApplication1.ServiceReference1.ActivationModelTelephonyProductActivationData { 

     private string item1Field; 

     private short item2Field; 

     [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)] 
     public string item1 { 
      get { 
       return this.item1Field; 
      } 
      set { 
       if ((object.ReferenceEquals(this.item1Field, value) != true)) { 
        this.item1Field = value; 
        this.RaisePropertyChanged("item1"); 
       } 
      } 
     } 

     [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)] 
     public short item2 { 
      get { 
       return this.item2Field; 
      } 
      set { 
       if ((this.item2Field.Equals(value) != true)) { 
        this.item2Field = value; 
        this.RaisePropertyChanged("item2"); 
       } 
      } 
     } 
    } 
} 

Nie ma podklasy do ActivationModelTelephonyProductActivationData (część ActivationModel jest przestrzeń nazw), który reprezentuje wartości, które nie posiadają żadnych danych i nie ma żadnych właściwości w klasie bazowej, gdzie możesz ustawić wartości, które nie mają żadnych danych.

Moje pytanie jest w końcu, jak się ma to zrobić. Czy muszę dodać "jednostkę" do wszystkich moich wartości dyskryminowanych, które nie mają danych.

Odpowiedz

1

Zasadniczo zależy to od szczegółów implementacji (skompilowanej postaci użytkowników), aby to działało. Nawet zmiana każdego przypadku, by była nie-nullarna, jest dla mnie hackowata. Myślę, że idealnym rozwiązaniem jest wykorzystanie klas. DU w przybliżeniu odpowiada abstrakcyjnej klasie bazowej dla typu DU i podklasy dla każdego przypadku. Możesz samodzielnie utworzyć hierarchię typów, osiągnąć podobny efekt i uzyskać lepsze wyniki.

EDIT: Skompilowany forma dalszych użytkowników, natomiast szczegółów wdrażania, jestdefined in the spec a zatem mało prawdopodobne, aby zmienić. Jednak samodzielne układanie typów sprawia, że ​​jest to jednoznaczne i uniemożliwia pracę nad przypadkami null.

3

Jeśli zdefiniujesz typ DU, jak poniżej, zadziała.

[<KnownType("KnownTypes")>] 
//[<DataContract>] // note: keep KnownTypes, but avoid DataContract 
// so that DataContractSerializer uses .NET 'Serializable' instead 
type TelephonyProductActivationData = 
    | MobileUseNextIcc 
    | Mobile of decimal 
    | MobileBroadbandUseNextIcc 
    | MobileBroadband of decimal 
    | Fixed 
    | Voip of int16 * int16 
    static member KnownTypes() = 
     typeof<TelephonyProductActivationData>.GetNestedTypes(BindingFlags.Public ||| 
                  BindingFlags.NonPublic) 
     |> Array.filter FSharpType.IsUnion 
+0

Brakowało mi tego w moim poście powyżej. Oczywiście DU miał atrybut knowntype. – Kristian

Powiązane problemy