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。
为什么让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,那么您有几个选项:
-
您可以在DbContext上显式使用.Include("AnotherObject")来获取对象。我通过让Read方法获取一个字符串数组来使用它,我用它来包括所有必要的对象。这比自动获取所有对象更理想,因为在序列化过程中,如果您获取所有对象,则很容易导致整个数据库被序列化,这会带来性能和安全问题等。
-
另一种选择是通过在列表前面添加关键字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,这样您就可以一次处理尽可能少的变量。