将实例转换为通用接口而不知道类型

时间:2016-01-15 11:35:04

标签: c# generics

我有一个名为IValueBridge的通用接口,它通过提供属性名称(也可以是嵌套属性,例如myFoo.MyProp.Name)作为通用桥接来从任意对象获取值:

public interface IValueBridge<in T> : IValueBridge
{
    object GetValue(T instance, string attributeName);
}

现在有一个实施类:

public class ValueBridge<T> : IValueBridge<T>
{
    public object GetValue(T instance, string attributeName)
    {
        Func<T, object> f = // ...
        return f(instance);
    }
}

现在有了这个设置,我想要使用那个桥接器来获取任意对象的值而不知道它在compile-type中的类型。

我想要实现的是类似的东西:

object bar = ...;
var bridge = new ValueBridge<typeof(bar>();

我知道如何使用MakeTypeGeneric通过反射创建泛型类型的实例。但Activator.CreateInstance返回的是object,我无法将其转换为实际类型Bar(我在编译时不知道),因此无法访问GetValue<T>在上面。

我有没有办法在没有任何反思的情况下访问GetValue<T>?我想避免更多的反射,因为经常调用该方法并通过反射调用它被认为是非常慢的。这就是为什么我要缓存要在里面调用的Func<T, object>

1 个答案:

答案 0 :(得分:1)

我找到了一个使用IValueBridge<T>扩展的包装器接口的非常好的解决方案:

public interface IValueBridge 
{
    object GetValue(object instance, string attributeName);
}

现在我的实际ValueBridge看起来像这样:

public class ValueBridge<T> : IValueBridge<T>
{
    object IValueBridge.GetValue(object instance, string attributeName)
    {
        return this.GetValue((T)instance, attributeName);
    }

    public object GetValue(T instance, string attributeName)
    {
        Func<T, object> f = // ...
        return f(instance);
    }

现在您可以使用((IValueBridge) myBridge).GetValue(...)。由于参数可以转换为ValueBridge(T) instance))中的实际类型,我们现在可以直接调用方法的泛型版本而无需任何反射。

请注意,您必须明确地实现这两个接口中的任何一个,以避免混淆从包装器中调用哪个方法。

我自我回答这个问题的原因是我对解决问题感到非常头疼,并希望将我的想法结果分享给社区。