私が直接値を設定して使用することが少し楽に実際に上記gsharpのポストを修正しました。 DynamicCast機能が導入されているため理想的ではありません。あなたのタイプアップを知っておく必要があります。私の目標は、私たちを強く型付けし、オブジェクトを返さず、動的なキーワードを避けようとすることでした。また、「魔法」を最小限に抑えてください。
public static T DynamicCast<T>(this object value)
{
return (T) value;
}
public static object GetPropertyValue<T>(this PropertyInfo propertyInfo, T objectInstance)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, propertyInfo.PropertyType);
var lambda = Expression.Lambda(convert, instance).Compile();
var result = lambda.DynamicInvoke(objectInstance);
return result;
}
public static void SetPropertyValue<T, TP>(this PropertyInfo propertyInfo, T objectInstance, TP value)
where T : class
where TP : class
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
var argument = Expression.Parameter(propertyInfo.PropertyType, "a");
var setterCall = Expression.Call(
instance,
propertyInfo.GetSetMethod(),
Expression.Convert(argument, propertyInfo.PropertyType));
var lambda = Expression.Lambda(setterCall, instance, argument).Compile();
lambda.DynamicInvoke(objectInstance, value);
}
例:
public void Get_Value_Of_Property()
{
var testObject = new ReflectedType
{
AReferenceType_No_Attributes = new object(),
Int32WithRange1_10 = 5,
String_Requires = "Test String"
};
var result = testObject.GetType().GetProperty("String_Requires").GetPropertyValue(testObject).DynamicCast<string>();
result.Should().Be(testObject.String_Requires);
}
public void Set_Value_Of_Property()
{
var testObject = new ReflectedType
{
AReferenceType_No_Attributes = new object(),
Int32WithRange1_10 = 5,
String_Requires = "Test String"
};
testObject.GetType().GetProperty("String_Requires").SetPropertyValue(testObject, "MAGIC");
testObject.String_Requires.Should().Be("MAGIC");
}
あなたラムダは、PropertyInfoオブジェクトに基づいては、DynamicCastを呼び出すとを避けるために型指定された呼び出しを行う作るためにMakeGenericMethodまたは式ツリーを使用するヘルパーメソッドを書くことができそれを前もって知っている。しかしそれはあまりエレガントではありません。
あなたの目標は何ですか?ラムダ式を作成したいとします。コンパイルされたデリゲート( 'functionThatGetsValue')だけが必要なのでしょうか、それとも中間式ツリー(' expression')も必要ですか? – LukeH
@LukeH、ちょうどコンパイルされたデリゲート。ありがとう。 (私の目標は、オブジェクトのリストを反復し、プロパティからすべての値を読み取ることです。少しのパフォーマンスを得るには、反射を使用するのではなく、このようにしたい) – gsharp
同様の結果を達成しようとすると、 Funcを返し、呼び出し側の特定のプロパティタイプに戻り値をキャストします。 –