1

サーバーサイドでWCFエラーが発生します:

パラメータhttp://tempuri.org/:GetUserResultをシリアル化しようとしたときにエラーが発生しました。InnerExceptionメッセージは「タイプ」でした。データコントラクト名が「RoleProxy:http://schemas.datacontract.org/2004/07/」の「RoleProxy」は予期されていません。..。

私の問題は、シリアル化できる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);

    ...

}

結果はサーバーによって正しく受信されますが、私が見つけたシリアル化の問題がいくつかあります。解決策はありますか?

ありがとう。

4

1 に答える 1

2

EFやNHibernateなどのORMは、デフォルトの動作を拡張するプロキシタイプを実行時に作成することを好みます。ほとんどの通常のコードは、サブタイプ(リスコフの置換原則など)を気にしませんが、継承を意識したシリアライザーは、実際に操作しているオブジェクトをチェックする必要があります。

動的プロキシタイプを扱うのは面倒です。一部のシリアライザーは一部のプロキシを処理できます(つまり、プロキシを予期しないサブタイプとして扱わず、代わりに基本タイプであるかのようにシリアル化します)が、それは決して普遍的ではありません。最も実用的な方法は、データをRoleインスタンスにマップし直して、 WCFに提供するものが指定したオブジェクトであることを確認することです。AutoMapperは、そのような便利な実装を作成する可能性があります。

追加の観察として、これはEqualsコードが間違っていることも意味します。

    if (obj.GetType() != typeof(Role)) return false;
    return Equals((Role)obj);

する必要があります:

    return Equals(obj as Role);

(それはすでに私たちのためにケースを正しくEquals(Role)処理していることに注意してください)null

于 2012-09-19T09:16:06.960 に答える