I'm trying to abstract away my interface implementations by providing a factory/builder using generics. However, I'm running into an issue with multiple dispatch and C# generics at run time that's doing something that seems odd.
The basic scenario is I've defined several interfaces:
public interface IAddressModel
{
}
public interface IUserModel
{
}
Then I have a factory class to return the actual implementations:
public class Factory
{
public T BuildModel<T>()
{
return BuildModel(default(T));
}
public object BuildModel(object obj)
{
//this is here because the compiler will complain about casting T to
//the first inteface parameter in the first defined BuildModel method
return null;
}
public IAddressModel BuildModel(IAddressModel iModel)
{
//where AddressModel inherits from IAddressModel
return new AddressModel();
}
public IUserModel BuildModel(IUserModel iModel)
{
//where UserModel inherits from IUserModel
return new UserModel();
}
}
The issue is when the factory is called like this: new Factory().BuildModel<IAddressModel>()
The BuildModel(...) method that is dispatched at run time from generics is always the least derived form of T, in this case always object.
However, if you call new Factory().BuildModel(default(IAddressModel));
the correct method is displatched (most likely because this is done at compile time). It seems that dynamic dispatch with generics doesn't check the methods for the most derived type even though the method called should be the same whether it's done at compile time or run time. Ideally I'd like to make the BuildModel(...) methods private and only expose the generic method. Is there another way to get dynamic displatch to call the correct method at run time? I've tried changing the BuildModel<>()
implementation to return BuildModel((dynamic)default(T))
but this throws a run time error about not being able to determine which method to dispatch. Is there maybe a way to do this with contravariance and more interfaces?