5

私は事実上オブジェクトベースの列挙型であるクラスを持っています。クラスによって公開されるオブジェクトの静的セットがあり、すべてがこれらの同じインスタンスを使用します。例(プライベートコンストラクターに注意してください)

[DataContract]
public class FieldType
{
    public static readonly FieldType Default  = new FieldType(1, "Default");
    public static readonly FieldType Name     = new FieldType(2, "Name");
    public static readonly FieldType Etc      = new FieldType(3, "Etc");

    private FieldType(uint id, string name)
    {
        Id = id;
        Name = name;
    }

    [DataMember] public uint   Id   { get; private set; }
    [DataMember] public string Name { get; private set; }
    //snip other properties
}

これは、WCF全体でシリアル化する必要があるまではうまく機能します。はDataContractSerializer、コンストラクターをバイパスして新しいオブジェクトを作成します。これにより有効なFieldTypeオブジェクトが生成されますが、これは静的インスタンスの1つではない新しいインスタンスです。これにより、既知の静的値に対する参照比較が失敗します。

クラスのシリアル化動作をオーバーライドして、提供されたインスタンスにデータを入力する代わりにオブジェクトインスタンスを作成する方法はありますか?

4

2 に答える 2

8

私はあなたができると思う

[DataContract]
public class FieldType : IObjectReference
{
    object IObjectReference.GetRealObject(StreamingContext ctx)
        switch(Id) {
            case 1: return Default;
            case 2: return Name; // note this is a collision between static/non-static
            case 3: return Etc;
            default: throw new InvalidOperationException();
        }
    }
    public static readonly FieldType Default  = new FieldType(1, "Default");
    // note this is a collision between static/non-static
    public static readonly FieldType Name     = new FieldType(2, "Name");
    public static readonly FieldType Etc      = new FieldType(3, "Etc");

    private FieldType(uint id, string name)
    {
        Id = id;
        Name = name; // note this is a collision between static/non-static
    }

    [DataMember] public uint   Id   { get; private set; }
    // note this is a collision between static/non-static
    [DataMember] public string Name { get; private set; }
    //snip other properties
}

検証済み:

public static class Program
{
    static void Main()
    {
        var obj = FieldType.Default;

        using(var ms = new MemoryStream())
        {
            var ser = new DataContractSerializer(typeof (FieldType));
            ser.WriteObject(ms, obj);
            ms.Position = 0;
            var obj2 = ser.ReadObject(ms);

            bool pass = ReferenceEquals(obj, obj2); // true
        }
    }
}

ただし、を使用して実際のオブジェクトを識別するNameだけの場合は、シリアル化する意味がほとんどないように思われることに注意してください。Id

于 2012-04-11T11:06:32.490 に答える
5

静的オブジェクトとWCFによって作成されたオブジェクトとの等価性チェックが機能するように、Equalsand GetHashcode(および==and )をオーバーライドすることをお勧めします。!=

データ転送オブジェクト(DTO)は、オブジェクト指向の動作を目的としたものではなく、純粋に状態クラスです。しかし、私はあなたが直面している問題を理解することができます。

または、ドメインオブジェクトが上記のクラスで動作している間に、別のDTOを使用してデータを送信します。

于 2012-04-11T11:06:27.030 に答える