2011-12-19 68 views
6

首先,我不得不說,我知道在.NET中與其他語言集成時使用F#特定的東西通常不是一個好主意。F#,序列化具有缺乏數據值的歧視聯盟

我的問題是,我不明白如何創建一個服務引用服務包含方法暴露歧視聯合。

我拿到那張有點像這樣的基礎:

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 

如果您使用F#交互首先創建類型:

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

而且你執行knowntypes代碼部分(略作修改):

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

,你會看到下面的輸出:

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

請注意,沒有與它們關聯的數據的值不見了。這意味着在編譯這個歧視聯盟時不會創建任何類型。通過執行在F#這種說法互動:

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

,我們將看到他們已經成爲:

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

正如你所看到的值,而與之相關聯的數據都成了屬性。現在我可以告訴你真正的問題。當創建一個服務參考服務用這種方法我得到的是這樣的:

[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"); 
       } 
      } 
     } 
    } 
} 

沒有子類ActivationModelTelephonyProductActivationData(該ActivationModel部分是命名空間),表示沒有任何數據值和有沒有屬性在基類中您可以設置沒有任何數據的值。

我的問題是最後,人們應該如何做到這一點。我是否必須將「單位」添加到沒有數據的所有區分的聯合數值中。

回答

1

您實質上依賴於實現細節(DU的編譯形式)以使其工作。即使將每種情況都改變爲非空洞的氣味,對我來說也是如此。我認爲理想的解決方案是使用類。 DU大致對應於DU類型的抽象基類和每種情況的子類。您可以自己創建類型層次結構,獲得類似的效果,並獲得更好的結果。

EDIT:下游用戶的已編譯的形式,而實現的細節,defined in the spec,因此不太可能改變。但是,自己佈置類型使其明確,並防止您必須在無用案件中工作。

3

如果像下面那樣定義DU類型,它將起作用。

[<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

我錯過了在我上面的帖子。當然,DU有知識類型屬性。 – Kristian 2012-01-17 13:58:30