简体   繁体   中英

Cast instance to generic interface without knowing type

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, eg 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM