2

リフレクションを使用する代わりに、式ツリーを使用してオブジェクト プロパティを設定および取得するにはどうすればよいですか?

私は正常に動作する以下のクラスを書きました:

public class PropertyAccessor<TEntity>
    {
        private readonly PropertyInfo _memberInfo;
        private readonly TEntity _nom;

        public PropertyAccessor(Expression<Func<TEntity, object>> fieldSelector, TEntity nom)
        {
            if (fieldSelector.Body is MemberExpression)
                _memberInfo = (PropertyInfo)((MemberExpression)fieldSelector.Body).Member;

            else if (fieldSelector.Body is UnaryExpression)
                _memberInfo = (PropertyInfo)((MemberExpression)((UnaryExpression)fieldSelector.Body).Operand).Member;
            else
                throw new NotImplementedException("Field selector not supported");

            _nom = nom;
        }

        public object Value
        {
            get { return _memberInfo.GetValue(_nom, null); }
            set { _memberInfo.SetValue(_nom, value, null); }
        }
    }

そして、私はそれを次のように使用します:

Product product = ProductFactory.Build();
var propertyAccessor = new PropertyAccessor<Product>(p => p.Name, product);
var name = propertyAccessor.Value;

パフォーマンスをさらに向上させる方法はありますか? 実装はそれを行うための最良の方法ですか?

コンストラクターの呼び出しの前または後に、式で Compile() メソッドを呼び出すべきではありませんか?

ラムダ式がそのラムダ式の Expression に渡されるとどうなりますか?

MemberExpression を PropertyInfo に変換するのが最善の選択肢ですか? パフォーマンスのペナルティはありますか?

4

1 に答える 1

1

プロパティは、実際には get と set という 2 つの別個のメソッドであることに注意してください。ここで式を使用する理由も見当たりませんでしたので、代わりにデリゲートを使用しました。式を使用する必要がある場合は、最初にコンパイルするだけです。

public class PropertyAccessor<TEntity,TProperty>
{
    private readonly TEntity _nom;
    Func<TEntity, TProperty> _getter;
    Action<TEntity, TProperty> _setter;

    public PropertyAccessor(Func<TEntity, TProperty> getter, Action<TEntity, TProperty> setter, TEntity nom)
    {
        _getter = getter;
        _setter = setter;
        _nom = nom;
    }

    public object Value // the return type can be changed to TProperty
    {
        get { return _getter(_nom); }
        set { _setter(_nom, (TProperty)value); }
    }
}

これは次のように呼び出すことができます。

var propertyAccessor = new PropertyAccessor<Product, String>(p => p.Name, (p, v) => p.Name = v, product);
于 2014-11-06T14:04:52.300 に答える