ジェネリックを使用してファクトリ/ビルダーを提供することにより、インターフェイスの実装を抽象化しようとしています。ただし、実行時に複数のディスパッチと C# ジェネリックで問題が発生し、奇妙なことを行っています。
基本的なシナリオは、いくつかのインターフェイスを定義したことです。
public interface IAddressModel
{
}
public interface IUserModel
{
}
次に、実際の実装を返すファクトリ クラスがあります。
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();
}
}
問題は、ファクトリが次new Factory().BuildModel<IAddressModel>()
のように呼び出される場合です。実行時にジェネリックからディスパッチされる BuildModel(...) メソッドは、常に T の最小派生形式であり、この場合は常にオブジェクトです。
ただし、new Factory().BuildModel(default(IAddressModel));
正しいメソッドを呼び出すと、ディスパッチされます (これはおそらくコンパイル時に行われるためです)。ジェネリックを使用した動的ディスパッチは、コンパイル時または実行時に呼び出されるメソッドが同じである必要があるにもかかわらず、最も派生した型のメソッドをチェックしないようです。理想的には、BuildModel(...) メソッドを非公開にして、ジェネリック メソッドのみを公開したいと考えています。動的ディスパッチが実行時に正しいメソッドを呼び出すようにする別の方法はありますか? BuildModel<>()
実装を変更しようとしましreturn BuildModel((dynamic)default(T))
たが、これにより、ディスパッチするメソッドを決定できないという実行時エラーがスローされます。反変性とより多くのインターフェースでこれを行う方法はありますか?