2

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.

MalibuCusser
  • 124
  • 1
  • 8
  • You can call the method via reflection, but it's not clear from your question if this is really the right solution. – Craig Stuntz Jan 13 '12 at 16:19
  • 1
    See this question: http://stackoverflow.com/questions/266115/pass-an-instantiated-system-type-as-a-type-parameter-for-a-generic-class – Ray Jan 13 '12 at 16:25
  • What do you expect `Foo` to do with the type `T` once it knows what it is? Is your real implementation of `Foo` more like `void Foo(T val)`? – M.Babcock Jan 13 '12 at 16:33
  • @M.Babcock No, I use `T` as a parameter to another method called in `Foo()`. I'll post a more complete example in a bit to help clarify the question. @Ray I did see that question and answer but asked mine because I feel the use of `dynamic` changes it up a bit. – MalibuCusser Jan 13 '12 at 16:41
  • possible duplicate of [How to use reflection to call generic Method?](http://stackoverflow.com/questions/232535/how-to-use-reflection-to-call-generic-method) – nawfal Jan 18 '14 at 07:40

3 Answers3

3

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; }
}
squirrel
  • 171
  • 2
1

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

Tigran
  • 61,654
  • 8
  • 86
  • 123
0

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

Chris Shain
  • 50,833
  • 6
  • 93
  • 125