【问题标题】:Cast instance to generic interface without knowing type在不知道类型的情况下将实例转换为通用接口
【发布时间】:2016-01-15 19:42:38
【问题描述】:

我有一个名为 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);
    }
}

现在有了这个设置,我想使用那个桥来获取任意对象的值,而不知道它在编译类型时的类型。

我想要达到的目标是这样的:

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

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

有没有一种方法可以让我无需更多反思就可以访问GetValue&lt;T&gt;?我想避免更多的反射,因为该方法经常被调用,并且通过反射调用它被认为很慢。这就是我缓存要在内部调用的Func&lt;T, object&gt; 的原因。

【问题讨论】:

  • 你试过动态吗?
  • 我想dynamic 会在内部使用反射来调用我非常想避免的成员。

标签: c# generics


【解决方案1】:

我找到了一个很好的解决方案,使用 IValueBridge&lt;T&gt; 扩展的包装接口:

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)) 中转换为它的实际类型,我们现在可以直接调用该方法的泛型版本而无需任何反射。

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

我自己回答这个问题的原因是我在解决这个问题时非常头疼,并想与社区分享我的想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多