Wcf F#,用缺少数据的值序列化有区别的并集

Wcf F#,用缺少数据的值序列化有区别的并集,wcf,serialization,f#,Wcf,Serialization,F#,首先,我必须说,我知道在与.NET中的其他语言集成时,使用F#特定的东西通常不是一个好主意 我的问题是,我不知道如何创建一个服务引用,该服务包含公开歧视联合的方法 我得到的基本知识有点像这样: type TelephonyProductActivationData = | MobileUseNextIcc | Mobile of decimal | MobileBroadbandUseNextIcc | MobileBroadband of decimal | Fixe

首先,我必须说,我知道在与.NET中的其他语言集成时,使用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#interactive中执行此语句:

typeof<TelephonyProductActivationData>.GetProperties() |> Array.map (fun x -> (x.Name));;
如您所见,没有与之关联的数据的值已成为属性。现在我可以告诉你真正的问题。使用此方法创建对服务的服务引用时,我得到的结果是:

[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");
                }
            }
        }
    }
}
ActivationModelEltelephonyProductActivationData(ActivationModel部分是名称空间)没有表示没有任何数据的值的子类,并且基类中没有可以设置没有任何数据的值的属性


最后,我的问题是,一个人应该如何做到这一点。我是否必须将“of unit”添加到所有没有数据的有区别的并集值中。

这基本上取决于实现细节(DU的编译形式)。即使把每一个案例都改成非无效案例,我也觉得很讨厌。我认为理想的解决方案是使用类。DU大致对应于DU类型的抽象基类和每种情况的子类。您可以自己创建类型层次结构,获得类似的效果,并获得更好的结果


编辑:DU的编译形式虽然是一个实现细节,但不太可能改变。但是,自己布置类型可以使其显式化,并防止您必须处理空值情况。

如果您像下面这样定义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 
[]
//[//注意:保留KnownTypes,但避免使用DataContract
//因此DataContractSerializer使用.NET“Serializable”
类型TelephonyProductActivationData=
|移动传感器
|十进制移动
|MobileBroadbandUseNextIcc
|十进制带
|固定的
|int16*int16的Voip
静态成员KnownTypes()=
typeof.GetNestedTypes(BindingFlags.Public|||
BindingFlags(非公开)
|>Array.filter FSharpType.IsUnion

我在上面的帖子中遗漏了这一点。当然,DU具有知识型属性。
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");
                }
            }
        }
    }
}
[<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