I want to create delegates to access properties of different objects without knowing them in advance.
I have the following definitions
public delegate T MyMethod<K, T>(K data);
public static MyMethod<K, T> CreatePropertyGetter<K, T>(PropertyInfo property)
{
MethodInfo mi = property.DeclaringType.GetMethod("get_" + property.Name);
return (MyMethod<K, T>)Delegate.CreateDelegate(typeof(MyMethod<K, T>), mi);
}
where T can be decimal, string, datetime or int
I have some initializing code that will create MyMethod delegates, based on the reflected properties of my object as follows:
foreach (PropertyInfo property in entityType.GetProperties())
{
switch (property.PropertyType.Name)
{
case "System.Decimal":
return CreatePropertyGetter<T, decimal>(property);
case "System.DateTime":
return CreatePropertyGetter<T, DateTime>(property);
case "System.String":
return CreatePropertyGetter<T, DateTime>(property);
}
}
Is there a better way to
EDIT:
My concern is performance, since these delegates will be called frequently (ticking scenario), so any casting will slow it down. While a more elegant solution is desirable, performance is still my main concern
I posted the same question on Code Review here, so i will mark this as solved considering the response there
A generic delegate can be defined the same way as a delegate but using generic type parameters or return type. The generic type must be specified when you set a target method. For example, consider the following generic delegate that is used for int and string parameters.
Delegates defined within a generic class can use the generic class type parameters in the same way that class methods do. Generic delegates are especially useful in defining events based on the typical design pattern because the sender argument can be strongly typed and no longer has to be cast to and from Object.
Func, Action and Predicate are generic inbuilt delegates present in System namespace. All three can be used with method, anonymous method and lambda expression.
This is something which could be posted on Code Review, and actually, I already posted a similar question. I believe my approach which uses expression trees already improves on your approach.
Example in usage:
Action<object> compatibleExecute =
DelegateHelper.CreateCompatibleDelegate<Action<object>>( owner, method );
Conversions are done when necessary. The method passed to the function here can have any type of parameter.
UPDATE:
I haven't tested this, but in your case you could try the following:
Func<object> getter =
DelegateHelper.CreateCompatibleDelegate<Func<object>>( owner, method );
method
must be set to the getter you retrieved. owner
must be set to the instance of your object. If you want to allow to pass the owner as an argument to the delegate, you'll have to adjust the code. An example is given by Vladimir Matveev as a comment on the article of Jon Skeet.
static Func<T, object, object> MagicMethod<T>(MethodInfo method)
{
var parameter = method.GetParameters().Single();
var instance = Expression.Parameter(typeof (T), "instance");
var argument = Expression.Parameter(typeof (object), "argument");
var methodCall = Expression.Call(
instance,
method,
Expression.Convert(argument, parameter.ParameterType)
);
return Expression.Lambda<Func<T, object, object>>(
Expression.Convert(methodCall, typeof (object)),
instance, argument
).Compile();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With