我在Serverside上遇到了WCF错误:
尝试序列化参数http://tempuri.org/:GetUserResult时出错。 InnerException消息是'Type'RoleProxy',数据协定名称为RoleProxy:http://schemas.datacontract.org/2004/07/'不是预期的。 ...
我的问题是,我没有任何可以序列化的RoleProxy类型。
我有以下课程:
[DataContract]
[KnownType(typeof(Permission))]
public class Role
{
protected virtual long _ID { get; set; }
[DataMember]
public virtual long ID
{
get { return _ID; }
// zum Test
set { _ID = value; }
}
[DataMember]
public virtual string Name { get; set; }
[DataMember]
public virtual bool IsDefault { get; set; }
[DataMember]
public virtual ICollection<Permission> Permissions { get; set; }
public Role()
{
}
public Role(string name, ICollection<Permission> permissions, bool isDefault = false)
{
Name = name;
Permissions = permissions;
IsDefault = isDefault;
}
public virtual bool HasPermission(Permission perm)
{
foreach(Permission permission in this.Permissions)
if (permission.Equals(perm))
return true;
return false;
}
public virtual bool Equals(Role other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(other.Name, Name);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != typeof(Role)) return false;
return Equals((Role)obj);
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
public override string ToString()
{
return Name;
}
}
这是我正在调用的函数:
[ServiceContract]
[ServiceKnownType(typeof(Role))]
[ServiceKnownType(typeof(User))]
[ServiceKnownType(typeof(Permission))]
[ServiceKnownType(typeof(IList<Role>))]
[ServiceKnownType(typeof(IList<User>))]
[ServiceKnownType(typeof(IList<Permission>))]
public interface ISecurityManager
{
...
[OperationContract]
User GetUser(string userDomain, string userName);
...
}
服务器正确接收了结果,但是我发现了一些序列问题。任何解决方案?
感谢。
答案 0 :(得分:2)
诸如EF和NHibernate之类的ORM喜欢在运行时创建代理类型来扩展默认行为。大多数常规代码不关心它是否具有子类型(Liskov替换原则等) - 但是:继承感知序列化器需要检查它们实际使用的对象。
处理动态代理类型很痛苦;一些序列化程序可以处理某些代理(即不将代理视为意外的子类型,而是将其序列化,好像它是基类型),但它绝不是通用的。最实际的做法是将您的数据映射回Role
实例,确保您给WCF的内容是您告诉它的对象。 AutoMapper可以为这样的实现方便实现。
作为补充观察,这也意味着您Equals
代码错误:
if (obj.GetType() != typeof(Role)) return false;
return Equals((Role)obj);
应该是:
return Equals(obj as Role);
(注意Equals(Role)
已经正确处理了null
案例)