3

、などのエンティティのクラスがあり、それぞれに 、などのマネージャ クラスがありますShip。すべてのマネージャ クラスは を実装し、エンティティは を実装します。ShampooHorseShipManagerShampooManagerHorseManagerIManagerIEntity

これで、エンティティを保存するためだけに記述された静的関数が次のようになります。

public static bool Save<S, T>(S entity, string msg) where S : IEntity 
                                                    where T : IManager<S>, new()
{
    string possibleError;
    switch (new T().Save(entity, out possibleError))
    {
        //---------------------
    }
    return true;
}

ここでの優雅さは、私がSave好きなSave<Radio, RadioManager>ものを呼び出さなければならないということです。私が欲しいのは、次のようなものです:

public static bool Save<T>(T entity, string msg) where T : IEntity
{
    string possibleError;
    switch ((/*find manager here*/).Save(entity, out possibleError))
    {
        //---------------------
    }
    return true;
}

これを行う方法はいくつかありますが、ジェネリックと型推論を含むものがあればいいのにと思います。エンティティ クラスと対応するマネージャー クラスを設計によって結合して、型の安全性も実現するのは良いことだと思います。

拡張メソッドの助けを借りて、私ができることは次のとおりです。

public static bool Save<T>(this IManager<T> mgr, T entity, string msg) where T : IEntity
{
    string possibleError;
    switch (mgr.Save(entity, out possibleError))
    {
        //---------------------
    }
    return true;
}

私が呼び出すことができるように:

FooManager fMgr = new FooManager();
fMgr.Save(foo, "success");

しかし、ここでは常に をインスタンス化し、そのインスタンスIManagerでメソッドを呼び出す必要がありSaveます。それほど多くの反復的なコードを避け、静的関数に義務を負わせたいと思っています。エンティティのマネージャが自動的に推論されるように、の間に関係を持つようにクラスを設計するにはどうすればよいですか?IManagerIEntity

編集:Saveマネージャークラスのメソッドをエンティティクラスに移動する余裕がないことに注意してください(これにより、作業が楽になります)。全体の設計は、1 つのエンティティ クラスと対応するマネージャー クラスに基づいています。なので、我慢しようと思っています。

4

2 に答える 2

4

FooManager のクライアントは、それが FooManager であるか、それとも IManager<Foo> であるかを気にしますか? IManager<Foo> だけが必要な場合は、AbstractFactoryパターンを確認することをお勧めします。ファクトリは、オンデマンドで正しい IManager をインスタンス化/取得する責任があります。ファクトリを配置すると、保存メソッドは次のようになります

public static bool Save<S>(S entity, string msg) 
  where S : IEntity
  {     
     string possibleError;     
     switch (ManagerFactory.GetManagerFor<S>().Save(entity, out possibleError))     
     {
       //---------------------     
     }     
     return true; 
  } 

ManagerFactory を実装するための最も簡単な方法は、サービス ロケーター/依存性インジェクターを使用して、IManager<T> 実装を自動検出することです。次に、GetManagerFor メソッドは、DI コンテナーからインスタンスを要求するだけです。たとえば、AutoFacでそれを行う方法は次のとおりです。

var dataAssembly = Assembly.GetExecutingAssembly();

builder.RegisterAssemblyTypes(dataAssembly)
    .Where(t => t.Name.EndsWith("Manager"))
    .AsClosedTypesOf(typeof(IManager<>);

これにより、autofac は、現在のアセンブリ内で名前が "Manager" で終わるすべてのクラスを検出し、IManager<T> の閉じた型として登録します。したがって、FooManager を見つけて、IManager<Foo> のインスタンスとして登録します。

ManagerFactory を呼び出すだけです。

return container.Resolve<IManager<Foo>>()

そして、あなたは金色です。私はあなたのためにあなたの申請書を書くつもりはありませんが、これはあなたが始めるのに十分なものになるはずです. AutoFac のドキュメントを読んでください。依存性注入を使用してオブジェクトを構築することもできるため、これは非常に強力であり、ベルトに持っておくべき優れたツールです。

于 2012-10-16T22:09:02.260 に答える
0

これが私がそれを解決した方法です。

Manager次のIEntityような関数を作成しました。

IManager<T> Manager<T>() where T : IEntity;

IEntityエンティティクラスのいずれかを実装するときはいつでも、それぞれのクラスも実装する必要がありManagerます。たとえば。

public class Foo : IEntity
{
    public IManager<T> Manager<T>() where T : IEntity
    {
        return (IManager<T>)new FooManager();
    }
}

今私は呼び出すことができます:

public static bool Save<T>(T entity, string msg) where T : IEntity, new()
{
    string possibleError;
    switch (entity.Manager<T>().Save(entity, out possibleError))
    {
        //--------------------------------------
    }
    return true;
}

最高のデザインではありませんが、これでうまくいきます..

于 2012-10-18T14:17:10.200 に答える