MalibuCusser
MalibuCusser

Reputation: 124

Get property type to pass to generic method

I need to get the type of a property that will only be known at run time and pass this as a type parameter for a generic method. For example:

PropertyInfo prop = Bar.GetProperty("Property1");

//"type 'prop' could not be found" error
Foo<prop.PropertyType>();

void Foo<T>()
{
   //Stuff
}
class Bar
{
   string Property1{get;set;}
}

The type of Bar.Property1 will not be known at compile time, so I can't do Foo<string>();. It will compile and run correctly if I use Foo<dynamic>(); but I'm not convinced that's the best way to go, and I'd like to know if there is a way to do it using an older framework.


Hopefully, this more complete example will make my intentions clearer:

    public void Map(TInType inObject, TOutType outObject)
    {
        //propertyIn, propertyOut, and converter are all strings identifying the properties/methods to be used from the inObject/Type outObject/Type.
        SetPropertyValues<dynamic, dynamic>(inObject, outObject, propertyIn, propertyOut, converter);
    }
    private void SetPropertyValues<TPropIn,TPropOut>(TInType fromObject, TOutType toObject, string propertyIn, string propertyOut, string converter)
    {
        PropertyInfo prop1 = typeof(TInType).GetProperty(propertyIn);
        MethodInfo converterMethod = typeof(TInType).GetMethod(converter);
        PropertyInfo prop2 = typeof(TOutType).GetProperty(propertyOut);

        prop2.SetValue(
            toObject,
            CopyPropertyValue<TPropIn, TPropOut>((TPropIn)prop1.GetValue(fromObject, null), p => (TPropOut)converterMethod.Invoke(fromObject, new object[] { p })),
            null);
    }
    private TPropOut CopyPropertyValue<TPropIn, TPropOut>(TPropIn InPropValue, Func<TPropIn, TPropOut> converterFunction)
    {
        return converterFunction(InPropValue);
    }

I'm open to any other suggestions anyone may have, or that the code should be taken out back and shot, but my original question is still the one I'm most interested in.

Upvotes: 2

Views: 3237

Answers (3)

squirrel
squirrel

Reputation: 171

You can use MakeGenericMethod, performance is actually quite reasonable and allows you to explicitly define what you are calling with what, so reduces the overhead. So something like the following, the Invoker would call the explicit method / class you need, and the helper actually invokes the generic call.

public class GenericHelper
{
    public static void DoSomethingGeneric(GenericInvokerParameters parameters)
    {
        var targetMethodInfo = typeof(GenericInvoker).GetMethod("DoSomethingGeneric");
        var genericTargetCall = targetMethodInfo.MakeGenericMethod(parameters.InvokeType);
        genericTargetCall.Invoke(new GenericInvoker(), new[] { parameters });
    }
}

public class GenericInvoker
{
    public void DoSomethingGeneric<T>(GenericInvokerParameters parameters)
    {
        //Call your generic class / method e.g.
        SomeClass.SomeGenericMethod<T>(parameters.SomeValue);
    }
}

public class GenericInvokerParameters
{
    public GenericInvokerParameters(Type typeToInvoke, string someValue)
    {
        SomeValue = someValue;
        InvokeType = typeToInvoke;
    }

    public string SomeValue { get; private set; }
    public Type InvokeType { get; private set; }
}

Upvotes: 3

Chris Shain
Chris Shain

Reputation: 51369

Foo should not be generic if you are not using it generically. Just make it operate on type Object instead of T.

Upvotes: 0

Tigran
Tigran

Reputation: 62265

Don't see anything bad in dynamic. Use it.

EDIT

Till you're not going to call that method with high frequency, where the reflection could bit it from performance perspective, I would prefer dynamic

Upvotes: 1

Related Questions