DynamicInvoke
не сделает установившего исполнителя.Здесь лучше использовать отражение от общего внутреннего типа, поскольку это позволит вам использовать типизированных делегатов.Другой вариант - DynamicMethod
, но вам нужно беспокоиться о некоторых деталях IL.
Вы могли бы захотеть взглянуть на HyperDescriptor
, что превращает работу IL в PropertyDescriptor
реализация.Другим вариантом является Expression
API (если вы используете .NET 3.5 или выше):
static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
{
MethodInfo setMethod = property.GetSetMethod();
if (setMethod != null && setMethod.GetParameters().Length == 1)
{
var target = Expression.Parameter(typeof(T));
var value = Expression.Parameter(typeof(object));
var body = Expression.Call(target, setMethod,
Expression.Convert(value, property.PropertyType));
return Expression.Lambda<Action<T, object>>(body, target, value)
.Compile();
}
else
{
return null;
}
}
Или альтернативно с универсальным типом:
abstract class Setter<T>
{
public abstract void Set(T obj, object value);
}
class Setter<TTarget, TValue> : Setter<TTarget>
{
private readonly Action<TTarget, TValue> del;
public Setter(MethodInfo method)
{
del = (Action<TTarget, TValue>)
Delegate.CreateDelegate(typeof(Action<TTarget, TValue>), method);
}
public override void Set(TTarget obj, object value)
{
del(obj, (TValue)value);
}
}
static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
{
MethodInfo setMethod = property.GetSetMethod();
if (setMethod != null && setMethod.GetParameters().Length == 1)
{
Setter<T> untyped = (Setter<T>) Activator.CreateInstance(
typeof(Setter<,>).MakeGenericType(typeof(T),
property.PropertyType), setMethod);
return untyped.Set;
}
else
{
return null;
}
}