2

100 を超えるプロパティを持つオブジェクトがあります。次に、これらのオブジェクトがたくさんあるリストを作成します。リスト内のすべてのプロパティについて、最小、最大、中、中央値を計算する必要があります。

したがって、書く代わりに:

Ag = _valuesForExtraCalculations.Min(c => c.Ag),
Al = _valuesForExtraCalculations.Min(c => c.Al),
Alkal = _valuesForExtraCalculations.Min(c => c.Alkal),

その 100 回、リフレクションを使用できると思ったので、次のように書きました。

var Obj = new Analysis();
Type t = Obj.GetType();
PropertyInfo[] prop = t.GetProperties();
foreach (var propertyInfo in prop)
{
    propertyInfo = _valuesForExtraCalculations.Min(?????);
}

しかし、foreach ループに何を記述すればよいかわからないので、そのプロパティの新しい最小値を、作成した新しい Analysis オブジェクトに設定できます。

4

2 に答える 2

4

私があなたの質問を理解している限り、あなたは式を使ってこれを達成することができます:

/// <summary>
/// A class with many-many properties
/// </summary>
class MyClass
{
    public Decimal A { get; set; }
    public Decimal B { get; set; }
    public Decimal C { get; set; }
}

class PropertyHelper<T, TProperty>
{
    private readonly Func<T, TProperty> selector;
    private readonly Action<T, TProperty> setter;

    public PropertyHelper(Func<T, TProperty> selector, Action<T, TProperty> setter)
    {
        this.selector = selector;
        this.setter = setter;
    }

    public Func<T, TProperty> Selector
    {
        get { return selector; }
    }

    public Action<T, TProperty> Setter
    {
        get { return setter; }
    }
}

class AggregateHelper<T, TProperty>
{
    private readonly Dictionary<PropertyInfo, PropertyHelper<T, TProperty>> helpers;

    public AggregateHelper()
    {
        this.helpers = typeof(T)
            .GetProperties()
            .Where(p => p.PropertyType == typeof(TProperty))
            .ToDictionary(p => p, p => new PropertyHelper<T, TProperty>(MakeSelector(p), MakeSetter(p)));
    }

    private Func<T, TProperty> MakeSelector(PropertyInfo property)
    {
        var parameterExpr = Expression.Parameter(typeof(T));
        var lambda = (Expression<Func<T, TProperty>>)Expression.Lambda(
            Expression.Property(parameterExpr, property), parameterExpr);

        return lambda.Compile();
    }

    private Action<T, TProperty> MakeSetter(PropertyInfo property)
    {
        var instanceExpr = Expression.Parameter(typeof(T));
        var parameterValueExpr = Expression.Parameter(typeof(TProperty));
        var lambda = (Expression<Action<T, TProperty>>)Expression.Lambda(
            Expression.Call(instanceExpr, property.GetSetMethod(), parameterValueExpr),
            instanceExpr,
            parameterValueExpr);

        return lambda.Compile();
    }

    public IEnumerable<PropertyInfo> Properties
    {
        get { return helpers.Keys; }
    }

    public PropertyHelper<T, TProperty> this[PropertyInfo property]
    {
        get { return helpers[property]; }
    }
}

使用法:

    public static void Do()
    {
        var target = new MyClass();
        var list = new List<MyClass>
        {
            new MyClass { A = 1M, B = 2M, C = 3M },
            new MyClass { A = 10M, B = 20M, C = 30M },
            new MyClass { A = 100M, B = 200M, C = 300M }
        };

        // calculate 'min' for all decimal properties
        var helper = new AggregateHelper<MyClass, Decimal>();

        foreach (var property in helper.Properties)
        {
            var propertyHelper = helper[property];

            propertyHelper.Setter(target, list.Min(propertyHelper.Selector));
        }
    }

コンパイルされたラムダはリフレクションよりも高速に動作し、ボクシング/アンボクシングはありません。

于 2012-05-16T13:08:13.043 に答える