Reputation: 124
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
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
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
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