获取属性类型以传递给泛型方法

时间:2012-01-13 16:17:19

标签: c# generics c#-4.0

我需要获取仅在运行时知道的属性类型,并将其作为泛型方法的类型参数传递。例如:

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;}
}

在编译时不知道Bar.Property1的类型,所以我不能Foo<string>();。如果我使用Foo<dynamic>();,它将正确编译并运行,但我不相信这是最好的方法,我想知道是否有办法使用旧框架。


希望这个更完整的例子能让我的意图更清晰:

    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);
    }

我对任何人可能提出的任何其他建议持开放态度,或者该代码应该被取回并拍摄,但我原来的问题仍然是我最感兴趣的问题。

3 个答案:

答案 0 :(得分:2)

您可以使用MakeGenericMethod,性能实际上非常合理,并且允许您使用什么来显式定义您正在调用的内容,从而减少开销。 所以类似下面的内容,Invoker会调用你需要的显式方法/类,而helper实际上会调用泛型调用。

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; }
}

答案 1 :(得分:1)

dynamic中看不到任何不良内容。 使用它。

编辑

直到您不打算以高频率调用该方法,其中反射可能从性能角度对其进行定位,我更希望dynamic

答案 2 :(得分:0)

如果您不使用它,那么Foo不应该是通用的。只需使它在Object类型而不是T上运行。