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

本文关键字:属性 数组 新手 问题 wcf | 更新日期: 2023-09-27 17:59:42

我有一个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。

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

为什么让RoleId属性自动实现而不让UserRoles实现?由于您有一个空的setter,所以按原样执行的代码将不起作用。你可能只需要使用一个auto属性:

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

或者至少提供一个有意义的设定者。setter不执行任何操作,因此反序列化程序无法填充该值。

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

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

userRolesTable = value;

另外,您的DataContract属性应该有公共设置程序。

UserRoles属性上的Setter设置为内部。因为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。

您需要实现setter。。。

protected internal set { userRolesTable = value; }

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

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

如果在调用之前对象被返回为null,那么您有几个选项:

  1. 您可以在DbContext上显式使用.Include("AnotherObject")来获取对象。我通过让Read方法获取一个字符串数组来使用它,我用它来包括所有必要的对象。这比自动获取所有对象更理想,因为在序列化过程中,如果您获取所有对象,则很容易导致整个数据库被序列化,这会带来性能和安全问题等。

  2. 另一种选择是通过在列表前面添加关键字virtual来使用动态代理。不过,DataContractSerializer在序列化动态代理时遇到问题,因此您需要实现一个使用ProxyDataContractResolver而不是DataContractResolve的属性。此属性需要应用于所有可以传递动态代理的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) { }
    }
    

编辑:我还认为你可以让数据合同中的setter不公开,因为我这样做了,效果很好:)。但我会尝试先将您的setter公开,然后解决问题,然后恢复到受保护的setter,这样您就可以一次处理尽可能少的变量。