wcf新手问题:数组作为属性

时间:2011-06-21 14:36:27

标签: c# wcf

我有DataContract类,它具有类型List<AnotherObject>的属性。 AnotherObject也标有DataContract。出于某种原因,这个属性来自wcf服务为null,尽管我在服务器上填充它。这是设计的吗?

你走了。类定义:

[DataContract]
    public class UserInfo
    {
        [DataMember]
        public decimal UserID
        {
            get;
            protected internal set;
        }

        [DataMember]
        public string UserName
        {
            get;
            protected internal set;
        }

        [DataMember]
        public string Pswd
        {
            get;
            protected internal set;
        }       

        [DataMember]
        public List<decimal> RoleID
        {
            get;
            protected internal set;
        }

        List<UserRole> userRolesTable = new List<UserRole>();
        [DataMember]
        public List<UserRole> UserRoles
        {
            get
            {
                return userRolesTable;
            }
            protected internal set { }
        }       
    }



[DataContract]
    public class UserRole
    {
        [DataMember]
        public decimal ROLEID { get; internal set; }

        [DataMember]
        public string ROLE_CODE { get; internal set; }

        [DataMember]
        public string ROLE_DESCRIPTION { get; internal set; }

        [DataMember]
        public decimal FORMID { get; internal set; }

        [DataMember]
        public string FORMCODE { get; internal set; }

        [DataMember]
        public string FORMNAME { get; internal set; }
    }

UserRoles属性为null。

5 个答案:

答案 0 :(得分:3)

为什么要让RoleId属性自动实现而不是UserRoles?代码按原样不起作用,因为你有一个空的setter。你应该只为它使用一个自动属性:

[DataMember]
public List<UserRole> UserRoles
{
    get; set;
}      

或者至少提供一个有意义的二传手。你的setter什么都不做,因此反序列化器无法填充该值。

答案 1 :(得分:1)

List<UserRole> userRolesTable = new List<UserRole>();
[DataMember]
public List<UserRole> UserRoles
{
    get
    {
        return userRolesTable;
    }
    protected internal set { }
} 

你的二传手是空的。放一些

userRolesTable = value;

另一方面,您的DataContract属性应该有 public setter。

答案 2 :(得分:1)

UserRoles属性上的Setter设置为internal。因为WCF框架将设置属性,所以它放弃了赋值,因为它被列为内部。

http://connect.microsoft.com/data/feedback/details/625985/wcf-client-entities-with-internal-setters-and-internalsvisibletoattribute-on-asmbly-fail

您可以使用该属性上的InternalsVisibleToAttribute属性执行此链接建议的内容,但我从未使用过它。

更新 我想说的是我打赌序列化工作正常,WCF框架无法将反序列化的值插入到主机代码中,因为根据数据契约,属性的内部Setter部分是不可访问的。使用InternalVisibleTo属性通知WCF序列化框架访问数据协定对象的客户端版本的setter。

答案 3 :(得分:0)

您需要实施setter ...

protected internal set { userRolesTable = value; }

答案 4 :(得分:0)

基本上,它是一个序列化问题。我过去在代码中遇到过这个问题,但已经有一段时间了,所以请耐心等待。

首先,我们需要在WCF调用之前找出对象关系是否为null,因此请在之前和之后进行调试。

如果在调用之前将对象返回为null,则有几个选项:

  1. 您可以在DbContext上显式使用.Include(“AnotherObject”)来获取对象。我通过让我的Read方法获取一个字符串数组来使用它,我过去常常包含所有必需的对象。这比自动获取所有对象更理想,因为在序列化期间,如果你采取一切措施,你可以很容易地将整个数据库序列化,这会引入性能和安全问题等等。

  2. 另一种选择是通过在列表前面添加关键字virtual来使用动态代理。但是,DataContractSerializer在序列化动态代理时遇到问题,因此您需要实现一个使用ProxyDataContractResolver而不是DataContractResolver的属性。此属性需要应用于可以传递动态代理的所有OperationContracts。这将自动获取所有对象引用,这可能是错误的编码实践,所以我建议使用上面的方法。

    public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
    {
    
      public ApplyDataContractResolverAttribute() { }
    
      public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) { }
    
      public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
      {
        DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
      }
    
      public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
      {
        DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
      }
    
      public void Validate(OperationDescription description) { }
    
    }
    
  3. 编辑:另外我认为你可以让数据合同中的setter不公开,因为我这样做并且它工作正常:)。但我会尝试先让你的setter公开,然后解决问题,然后恢复到受保护的setter,这样你就可以尽可能少地处理变量。