C#のリフレクションを使って異なるクラスのオブジェクトの同名プロパティの値をコピーしてみる。

C# コンピュータ
C#

異なるオブジェクトで同名プロパティの値をコピーすることがあり、プリミティブな形なのでリフレクションで上手いこと処理できないかと思いコードを書いて見ました。

class MyClassA
{
    public string Name { get; set; } = "";
    public int Value {get; set; } = 0;
}

class MyClassB
{
    public string Name { get; set; } = "";
    public int Value {get; set; } = 0;
    public string Location { get; set; } = "NONE";
}

class Program
{
    // プロパティの値をコピー
    static void CopyPropertys(object src, object dst)
    {
        Type srcType = src.GetType();
        Type dstType = dst.GetType();

        foreach (var s in srcType.GetProperties())
        {
            // 同名プロパティが存在するか?
            var d = dstType.GetProperty(s.Name);
            if (d is null) continue;

            // 読み込み可能か?
            if (s.CanRead == false) continue;

            // 書き込み可能か?
            if (d.CanWrite == false) continue;

            // プロパティの形は同じか?
            if (s.PropertyType != d.PropertyType) continue;

            // 代入
            d.SetValue(dst, s.GetValue(src));
        }

    }
    static void Main()
    {
        
        var objA = new MyClassA()
        {
            Name = "BOB",
            Value = 77,
        };

        var objB = new MyClassB();


        CopyPropertys(objA, objB);

        Type type = objB.GetType();
        foreach (var p in type.GetProperties())
        {
            Console.WriteLine($"{p.Name}: {p.GetValue(objB)}");
        }
    }
}

結果

Name: BOB
Value: 77
Location: NONE

本来以下のようにプロパティ名を指定して一つ一つ代入するところをCopyPropertys()で一括処理しています。

objB.Name = objA.Name
objB.Value = objA.Value

さらに、対象のクラスのプロパティを増やした場合でもCopyPropertys()のコードは変更不要な点も便利だと思います。

ただし、プロパティがstringやintなどプリミティブ型なのでこれで良さそうですが、クラスのインスタンスなどの場合はClone()する必要があります。

コメント