我有一个名为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>
。
答案 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)
)中的实际类型,我们现在可以直接调用方法的泛型版本而无需任何反射。
请注意,您必须明确地实现这两个接口中的任何一个,以避免混淆从包装器中调用哪个方法。
我自我回答这个问题的原因是我对解决问题感到非常头疼,并希望将我的想法结果分享给社区。 p>