7

同じオブジェクトの2つのインスタンス、o1とo2があります。私が次のようなことをしている場合

 if (o1.property1 != null) o1.property1 = o2.property1 

オブジェクト内のすべてのプロパティ。オブジェクト内のすべてのプロパティをループしてそれを行う最も効率的な方法は何でしょうか?PropertyInfoを使用してプロパティのnulllをチェックしている人を見ましたが、PropertyInfoコレクションを介してのみ取得でき、プロパティの操作をリンクできなかったようです。

ありがとう。

4

3 に答える 3

14

あなたはリフレクションでこれを行うことができます:

public void CopyNonNullProperties(object source, object target)
{
    // You could potentially relax this, e.g. making sure that the
    // target was a subtype of the source.
    if (source.GetType() != target.GetType())
    {
        throw new ArgumentException("Objects must be of the same type");
    }

    foreach (var prop in source.GetType()
                               .GetProperties(BindingFlags.Instance |
                                              BindingFlags.Public)
                               .Where(p => !p.GetIndexParameters().Any())
                               .Where(p => p.CanRead && p.CanWrite))
    {
        var value = prop.GetValue(source, null);
        if (value != null)
        {
            prop.SetValue(target, value, null);
        }
    }
}
于 2012-11-03T19:36:31.757 に答える
2

あなたの例から判断すると、私はあなたがこのようなものを探していると思います:

static void CopyTo<T>(T from, T to)
{
    foreach (PropertyInfo property in typeof(T).GetProperties())
    {
        if (!property.CanRead || !property.CanWrite || (property.GetIndexParameters().Length > 0))
            continue;

        object value = property.GetValue(to, null);
        if (value != null)
            property.SetValue(to, property.GetValue(from, null), null);
    }
}
于 2012-11-03T19:35:24.067 に答える
2

これを何度も使用する場合は、コンパイルされた式を使用してパフォーマンスを向上させることができます。

public static class Mapper<T>
{
    static Mapper()
    {
        var from = Expression.Parameter(typeof(T), "from");
        var to = Expression.Parameter(typeof(T), "to");

        var setExpressions = typeof(T)
            .GetProperties()
            .Where(property => property.CanRead && property.CanWrite && !property.GetIndexParameters().Any())
            .Select(property =>
            {
                var getExpression = Expression.Call(from, property.GetGetMethod());
                var setExpression = Expression.Call(to, property.GetSetMethod(), getExpression);
                var equalExpression = Expression.Equal(Expression.Convert(getExpression, typeof(object)), Expression.Constant(null));

                return Expression.IfThen(Expression.Not(equalExpression), setExpression);
            });

        Map = Expression.Lambda<Action<T, T>>(Expression.Block(setExpressions), from, to).Compile();
    }

    public static Action<T, T> Map { get; private set; }
}

そして、次のように使用します。

Mapper<Entity>.Map(e1, e2);
于 2012-11-04T07:21:58.447 に答える