I gsharp den Beitrag oben geändert habe, um tatsächlich den Wert direkt eingestellt und macht es ein bisschen einfacher zu bedienen. Es ist nicht ideal, da es die Einführung der DynamicCast-Funktion gibt, bei der Sie Ihren Typ im Voraus kennen müssen. Mein Ziel war es, uns stark typisiert zu halten und kein Objekt zurückzugeben und dynamisches Schlüsselwort zu vermeiden. Halten Sie auch "Magie" auf ein Minimum.
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);
}
Beispiele:
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");
}
Sie konnte eine Hilfsmethode schreiben, die Makegenericmethod oder einen Ausdruck Baum verwendet eine Lambda auszukommen den typisierten Anruf DynamicCast basierend auf dem Propertyinfo-Objekt zu rufen und zu vermeiden, um es im Voraus zu wissen. Aber das ist weniger elegant.
Was ist Ihr Ziel? Sie sagen, dass Sie einen Lambda-Ausdruck erstellen möchten. Benötigen Sie nur den kompilierten Delegaten ('functionThatGetsValue'), oder benötigen Sie auch den intermediate Ausdrucksbaum (' expression')? – LukeH
@LukeH, nur der kompilierte Delegat. Vielen Dank. (Mein Ziel ist es, durch eine Liste von Objekten zu iterieren und alle Werte aus den Eigenschaften zu lesen. Um ein bisschen Leistung zu bekommen, möchte ich es auf diese Weise tun, anstatt Reflektion zu verwenden) – gsharp
Als ich versuchte, ein ähnliches Ergebnis zu erzielen, endete ich mit Rückgabe von Func und Rückgabewert an bestimmten Eigenschaftstyp auf der Seite des Aufrufers zurückgegeben. –