コンパイル時にオブジェクトタイプを知らなくても、オブジェクトにプロパティ値を設定したい。高速にしたい(つまり、毎回Reflectionを使用しない)。プロパティの名前とタイプを知っています。
最速の方法(afaik)は、デリゲートを使用することです。これが私がこれまでに持っているものです:
class User // this is an example.. Assume I don't know which type this is.
{
public string Name {get;set;}
}
public static Action<object, object> CreatePropertySetter(Type targetType, string propertyName)
{
ParameterExpression targetObjParamExpr = Expression.Parameter(targetType);
ParameterExpression valueParamExpr = Expression.Parameter(targetType.GetProperty(propertyName).PropertyType);
MemberExpression propertyExpr = Expression.Property(targetObjParamExpr, propertyName);
BinaryExpression assignExpr = Expression.Assign(targetObjParamExpr, valueParamExpr);
Action<object, object> result = Expression.Lambda<Action<object, object>>(assignExpr, targetObjParamExpr, valueParamExpr).Compile();
return result;
}
それから私はこの電話をかけます:
User user = new User();
var userNameSetter = CreatePropertySetter(user.GetType(), "Name");
userNameSetter(user, "Bob");
ただし、Objectの代わりにUserタイプのobjectを渡すという事実は気に入らず、「Type'User'のParameterExpressionはタイプ'System.Objectのデリゲートパラメータには使用できません」で失敗します。
私は式ツリーに慣れていないので、ここで少し迷子になりました。ユーザーをオブジェクトにキャストできないのはなぜですか?どこかにキャストが必要ですか?
「アクション」も見栄えがよくありません。引数(User user、string propertyValue)をとるデリゲートを返すだけの方が良いでしょう。繰り返しますが、それを達成する方法がわかりません。実際、Delegate.CreateDelegateで試してみましたが、.Invoke()メソッドを使用して呼び出します。これは低速です(これが唯一の方法ですか?)。Expression.Lambda(非ジェネリック)と同じです。
何かご意見は ?
また、式ツリーに関する優れた(msdnよりも優れた)ドキュメントはありますか?msdnバージョンには本当に詳細が欠けています。