【问题标题】:WCF Service default valuesWCF 服务默认值
【发布时间】:2011-01-03 17:48:09
【问题描述】:

我的 WCF 服务有以下数据协定类:

[DataContract(Name = "MyClassDTO")]
public class MyClass
{
    private string name = "Default Name";

    [DataMember]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

当我使用 Visual Studio 的添加服务引用函数生成 WCF 服务引用时,生成的 DataContract 看起来像这样:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name = "MyClassDTO", Namespace = "xxx")]
[System.SerializableAttribute()]
public partial class MyClassDTO : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged
{

    [System.Runtime.Serialization.OptionalFieldAttribute()]
    private string NameField;

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

这意味着,默认值“默认名称”丢失并发生以下行为:

MyClassDTO mcdto = new MyClassDTO();
serviceClient.DoSomething(mcdto);


[OperationContract]
void DoSomething(MyClass mc){
   mc.Name //<--   == null    but I want it to be "Default Name"
}

有没有办法以这种方式配置数据合约,使定义的默认值“默认名称”不会丢失?

其他信息: 我使用服务引用没有在引用的程序集中重用类型,例如在客户端生成类 MyClassDTO 不知道服务器端类 MyClass

【问题讨论】:

    标签: c# .net visual-studio-2008 wcf


    【解决方案1】:

    到目前为止,我发现的唯一可能(但丑陋,因此并不真正令人满意)的解决方案是使用OnDeserializing 属性在反序列化开始时设置默认值,并使用字段的设置器来确定是否通信确实应该设置值。

       [DataContract(Name = "MyClassDTO")]
        public class MyClass
        {
            private string name;
    
            public MyClass()
            {
                Init();
            }
    
            [DataMember]
            public string Name
            {
                get{ return name; }
                set
                {
                    if (!String.IsNullOrEmpty(value))
                    {
                        name = value;
                    }
                }
            }
    
            private void Init()
            {
                name = "Default Name";
            }
    
            [System.Runtime.Serialization.OnDeserializing]
            private void OnDeserializing(StreamingContext ctx)
            {
                Init();
            }
      }
    

    【讨论】:

      【解决方案2】:

      嗯.. 我认为 [DefaultValue(...)] 有一些东西会起作用,但显然不是;不过,我有点困惑为什么你得到null - 因为你没有告诉它任何默认值,我希望"Default Name" 进入输出。如果您一些默认代码(或ShouldSerialize* / *Specified),那么您可以尝试:

      [DataMember(EmitDefaultValue=true)]
      public string Name {
          get { return name; }
          set { name = value; }
      }
      

      但同样 - 我不完全确定您为什么首先看到 null

      我刚刚使用基于 VS2008 中的 WCF 模板的东西对此进行了测试,效果很好:

      using (var client = new Service1Client()) {
          var result = client.GetDataUsingDataContract();
          Console.Write(result.Name); // "Default Name"
      }
      

      【讨论】:

      • 是的,方向服务器 -> 客户端可以正常工作。但在客户端-> 服务器方向上它不起作用。请注意,在客户端站点上,DataContract 类 MyClassDTO 是生成的,仅在客户端使用。客户端不知道 MyClass 并且服务器端不知道类 MyClassDTO
      【解决方案3】:

      我不相信 XML Schema 允许描述元素的默认值。这意味着,就您的服务客户而言,没有默认值。

      除此之外,您没有告诉 WCF 您的意思是使用默认值,因此即使有一种方法可以将您的意图传达给客户端,但事实是您并没有传达您的意图。

      【讨论】:

      • 那是因为我正在寻找一种沟通方式 :-) 但似乎(就像你说的那样)没有办法做到这一点。
      【解决方案4】:

      在反序列化期间,您的属性的“设置”逻辑将被执行,因此您可以在那里检查 null 并设置为您想要的默认值。

      【讨论】:

      • 这似乎是实现我目标的唯一方法。但是在反序列化过程中没有调用构造函数并且没有初始化对象,因此你必须使用 const 变量
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-28
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 2012-02-05
      相关资源
      最近更新 更多