rksoftware

Visual Studio とか C# とかが好きです

異なる型のオブジェクトに同じ名前のプロパティの値を全てセットする その2

大量のプロパティを持つオブジェクト間でプロパティの値をコピーしたいことがあります。
毎回コピーするコードを書くのも面倒なので、メモをしておきます。
昨日のコードは型が異なる場合に使えなかったので、雑に型変換処理を入れてみました。
下記コードの PropertyCopier クラスの CopyTo メソッドでコピーできます。

public static class PropertyCopier
{
    public static T CopyTo<T>(object src, T dest)
    {
        var it = typeof(int);
        if (src == null || dest == null) return dest;
        var srcProperties = src.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Where(p => p.CanRead && p.CanWrite);
        var destProperties = dest.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Where(p => p.CanRead && p.CanWrite);
        var properties = srcProperties.Join(destProperties, p => p.Name, p => p.Name, (p1, p2) => new { p1, p2 });
        foreach (var property in properties)
        {
            if (property.p1.PropertyType == property.p2.PropertyType)
            {
                property.p2.SetValue(dest, property.p1.GetValue(src));
            }
            else
            {
                var f =
                (property.p2.PropertyType == typeof(string)) ? v => Convert.ToString(v)
                    : (property.p2.PropertyType == typeof(short)) ? v => Convert.ToInt16(v)
                    : (property.p2.PropertyType == typeof(short?)) ? v => Convert.ToInt16(v)
                    : (property.p2.PropertyType == typeof(bool)) ? v => Convert.ToBoolean(v)
                    : (property.p2.PropertyType == typeof(bool?)) ? v => Convert.ToBoolean(v)
                    : (property.p2.PropertyType == typeof(int)) ? v => Convert.ToInt32(v)
                    : (property.p2.PropertyType == typeof(int?)) ? v => Convert.ToInt32(v)
                    : (property.p2.PropertyType == typeof(long)) ? v => Convert.ToInt64(v)
                    : (property.p2.PropertyType == typeof(long?)) ? v => Convert.ToInt64(v)
                    : (property.p2.PropertyType == typeof(double)) ? v => Convert.ToDouble(v)
                    : (property.p2.PropertyType == typeof(double?)) ? v => Convert.ToDouble(v)
                    : (property.p2.PropertyType == typeof(decimal)) ? v => Convert.ToDecimal(v)
                    : (property.p2.PropertyType == typeof(decimal?)) ? v => Convert.ToDecimal(v)
                    : (property.p2.PropertyType == typeof(DateTime)) ? v => Convert.ToDateTime(v)
                    : (property.p2.PropertyType == typeof(DateTime?)) ? v => Convert.ToDateTime(v)
                    : (Func<object, object>)null;
                try { property.p2.SetValue(dest, f?.Invoke(property.p1.GetValue(src))); } catch { property.p2.SetValue(dest, null); }
            }
        }
        return dest;
    }
}


class Program
{
    static void Main(string[] args)
    {
        var dest = PropertyCopier.CopyTo(new Test1() { Prop1 = "p1", Prop2 = "p2", Prop3 = "p3" }, new Test2());
        Console.WriteLine($"{dest.Prop1}, {dest.Prop2}, {dest.Prop3}");

        Console.ReadKey();
    }
}

public class Test1
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
}

public class Test2
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
}