Home > Software design >  C# cast type to generic interface without knowing interface type
C# cast type to generic interface without knowing interface type

Time:10-31

Is it possible to cast to a generic interface type where you don't know the actual generic type but DO know that the type is derived from some shared interface?

I have a generic interface:

public interface IFooGenericObjectProvider<TModel> where TModel : class, IBaseModelType
{
    SomeObject ProvideSomeObject(TModel model);
}

Classes implement it like so:

public class SomeObjectProvider : IFooGenericObjectProvider<ConcreteModel>
{
    public SomeObject ProvideSomeObject(ConcreteModel model)
    {
        // create instance of 'SomeObject' using 'ConcreteModel'
    }
}

And I'm creating instances of types which implement the IFooGenericObjectProvider<TModel> type via reflection / Activator.CreateInstance

This all works great however the issue arises when I need to use the created types.

I'm trying to cast them to IFooGenericObjectProvider<IBaseModelType> when I need to call the method from the implemented interface, and since all ConcreteModel instances derive from a shared IBaseModelType interface, I figured this would be perfectly fine but it throws an exception during the cast:

Unable to cast object of type 'SomeObjectProvider' to type 'IFooGenericObjectProvider`1[IBaseModelType]'.

I can fix this by changing to:

public class SomeObjectProvider : IFooGenericObjectProvider<IBaseModelType>
{}

However the caller is provided with an instance of IBaseModelType rather than ConcreteType which is what I would like:

public SomeObject ProvideSomeObject(IBaseModelType model)
{
    // This works, but would like access to the concrete model type instead
}

I know that I can cast IBaseModelType model to the concrete type but this isn't as nice and is an extra step for the caller.

Is what I'm trying to achieve possible? Perhaps theres another approach that would work better?

CodePudding user response:

I was able to work around this by invoking the method via reflection on the type/instance.

For exampple:

var providerInstance =  ActivatorUtilities.CreateInstance(this.serviceProvider, providerType);
var someObject = providerType.InvokeMember("ProvideSomeObject", BindingFlags.InvokeMethod, null, providerInstance, new object[] { model });
  • Related