Reputation: 37000
I have a generic interface called IValueBridge
which serves as a generic bridge to get the values from any arbitrary object by providing the properties name (also nested properties are possible, e.g. myFoo.MyProp.Name
):
public interface IValueBridge<in T> : IValueBridge
{
object GetValue(T instance, string attributeName);
}
Now there is an implementing class:
public class ValueBridge<T> : IValueBridge<T>
{
public object GetValue(T instance, string attributeName)
{
Func<T, object> f = // ...
return f(instance);
}
}
Now with this setting I wanto to use that bridge in order to get the values for any arbitrary object without knowing its type at compile-type.
What I WANT to achieve is something similar to this:
object bar = ...;
var bridge = new ValueBridge<typeof(bar>();
I know how to create instances of generic types via reflection using MakeTypeGeneric
. However what Activator.CreateInstance
returns is an object
and I cannot cast it to the actual type Bar
(which I don´t know at compile-time) and thus cannot access GetValue<T>
on it.
Is there a way I can access GetValue<T>
without any more reflection? I´d like to avoid more reflection as the method is called very often and calling it via reflection is considered quite slow. That´s why I cache the Func<T, object>
to be called inside.
Upvotes: 1
Views: 1279
Reputation: 37000
I found a quite nice solution using a wrapper-interface which IValueBridge<T>
extends:
public interface IValueBridge
{
object GetValue(object instance, string attributeName);
}
Now my actual ValueBridge
looks like this:
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);
}
Now you can use ((IValueBridge) myBridge).GetValue(...)
. As the parameter can be cast to its actual type within the ValueBridge
((T) instance)
) we can now invoke the generic version of the method directly without any reflection.
Note that you have to explicitely implement any of the two interfaces to avoid confusion which method to call from within the wrapper.
The reason I self-answer that question is that I got much head-ache on solving it and want to share the result of my thoughts to the community.
Upvotes: 1