この例では、同じインターフェイスから継承するさまざまなオブジェクトをジェネリック型で1つの変数に格納するにはどうすればよいですか?

Rob1n

2つのクラスで構成されるデータモデルがあり、どちらも同じインターフェイスを実装しているとします。

    interface IEntity { }
    class EntityTypeA : IEntity { }
    class EntityTypeB : IEntity { }

これらのエンティティのリストを含み、それらを使用して何かを行う汎用サービスがあります。サービスには複数の異なる実装があり、すべてIServiceから継承していますが、今のところ「サービス」は1つだけだとしましょう。

    interface IService<T> where T : class, IEntity {
        // stuff
        T GetEntity(Func<T, bool> linq);
    }

    class Service<T> : IService<T> where T : class, IEntity {
        // stuff
        IEnumerable<T> _entities;
    }

この時点で、さまざまなエンティティ用の新しいサービスを簡単に作成して操作できます。特定のタイプの新しいエンティティをそれらに追加し、メソッドを呼び出し、手動で何もキャストせずにそれらを取り戻します。

    IService<EntityTypeA> serviceA = new Service<EntityTypeA>();
    IService<EntityTypeB> serviceB = new Service<EntityTypeB>();

すべて問題ありませんが、これらすべてのサービスを1つの場所に保存して、後で必要なサービスをすべて個別の変数に保持しなくても簡単にフェッチできるようにします。

最終的に私はこのようなsthを実行できるようにしたかった:

    _manager = new ServiceManager();
    _manager.AddService("A", serviceA);
    _manager.AddService("B", serviceB);
    IService<EntityTypeA> serviceA = _manager.GetService<EntityTypeA>("A");

だから私はこのようなことを試みました:

class ServiceManager {
        IDictionary<string, IService<IEntity>> _services;

        public void AddService<T>(string key, IService<T> manager) where T : class, IEntity {
            _services[key] = (IService<IEntity>)manager;
        }

        public IService<T> GetService<T>(string key) where T : class, IEntity {
            return (IService<T>)_services[key];
        }
    }

ここでの問題は、「無効なキャスト例外」メソッド(だけでなくとしておそらくのgetService)にaddServiceを呼び出すことで、私はキャストや保存することができないService<EntityTypeA>にしIService<IEntity>EntityTypeAはIEntityを実装し、ServiceはIServiceを実装しているので、これは私にとって少し驚きでした...

だから私の質問は:これらすべての汎用サービスを単一の変数に格納して、マネージャーから1つのメソッドで簡単に取得できるようにするにはどうすればよいですか?このマネージャーをこれらすべてのサービスの管理を担当する単一のインスタンスにしたいのですが、これらすべてのジェネリッククラスを保持する方法がわかりません。

スイーパー

不変であるためService<EntityTypeA>格納することはできませんジェネリック型パラメーターは、特に宣言しない限り、デフォルトでは不変です。一般的には割り当てられません理由については、この投稿参照してくださいIService<IEntity>IServiceTFoo<Derived>Foo<Base>

内容に応じて// stuffであるIService、あなたが潜在的に作ることができT 、共変あなたがタイプの値を割り当てることができるように、IService<EntityTypeA>(したがってService<EntityTypeA>型の変数に)IService<IEntity>

これを行うにはoutT:に修飾子を追加ます。

interface IService<out T> where T : class, IEntity {
    // stuff
    T GetEntity(Func<T, bool> linq);
}

これはIServiceT(とりわけ)を取り込むメソッドがある場合は機能しません

interface IService<out T> where T : class, IEntity {
    // stuff
    T GetEntity(Func<T, bool> linq);
    void Foo(T t); // compiler error
}

これは型安全性を損なうので:

IService<IEntity> s = new Service<EntityTypeA>();
s.Foo(new EntityTypeB()); // breaks type safety! I can now give Service<EntityTypeA> a EntityTypeB object!

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ