Question

Using Jon Skeet's article Making reflection fly and exploring delegates as a guide, I am trying to use the Delegate.CreateDelegate method to duplicate properties as delegates. Here's an example class:

public class PropertyGetter
{
    public int Prop1 {get;set;}
    public string Prop2 {get;set;}

    public object GetPropValue(string propertyName)
    {
        var property = GetType().GetProperty(propertyName).GetGetMethod();
        propertyDelegate = (Func<object>)Delegate.CreateDelegate(typeof(Func<object>), this, property);

        return propertyDelegate();
    }
}

The problem I'm having is when I call GetPropValue and pass in "Prop1" as the parameter, I get an ArgumentException on the call to Delegate.CreateDelegate with the message "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type." This happens when using any property that returns a primitive/value type including structs.

Does anybody know a way to be able to use both reference and value types here?

Was it helpful?

Solution

Fundamentally your general approach isn't possible. The reason you're able to take all non-value types and treat them as a Func<object> is by relying on contravariance (Func<T> is contravariant with respect to T). As per the language specs, contravariance does not support value types.

Of course, the problem is easier if you just don't rely on using that approach.

If you just want to get the value use the PropertyInfo.GetValue method:

public object GetPropValue(string name)
{
    return GetType().GetProperty(name).GetValue(this);
}

If you want to return a Func<object> which will fetch the value whenever it's called, just create a lambda around that reflection call:

public Func<object> GetPropValue2(string name)
{
    return () => GetType().GetProperty(name).GetValue(this);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top