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 });