ここで議論する価値があると思うジレンマに遭遇しました。
IoC で解決される別の DAL からデータを取得する一連のドメイン オブジェクト (必要に応じてエンティティと呼ぶこともできます) があります。
システムを非常に拡張可能にすることを考えていましたが、IoC によってこれらのエンティティも解決することが正しいかどうか迷っています。
ばかげた例を提示しましょう。
次のインターフェイスを持つ Web サイトがあるとします。
public interface IArticleData
{
int ID { get; }
string Text { get; set; }
}
概念は、DAL がそのようなインターフェイスと汎用インターフェイスを実装することIDataProvider<TData>
です。その後、DAL は簡単に交換可能になります。そして、それを使用する次のクラスがあります。
public class Article
{
private IArticleData Data { get; set; }
public int ID
{
get { return Data.ID; }
}
public int Text
{
get { return Data.Text; }
set { Data.Text = value; }
}
private Article(IArticleData data)
{
Data = data;
}
public static FindByID(int id)
{
IDataProvider<IArticleData> provider = IoC.Resolve<IDataProvider<IArticleData>>();
return new Article(provider.FindByID(id));
}
}
これにより、システム全体が実際の DAL 実装 (例ではIDataProvider<IArticleData>
) から独立したものになります。
次に、この機能が実際には十分でない状況を想像して、拡張したいと考えています。上記の例では、それを行うオプションはありませんが、インターフェイスを実装する場合:
public interface IArticle
{
int ID { get; }
string Text { get; set; }
}
public class Article : IArticle
{
...
}
次に、Article クラスへのすべての依存関係を削除し、IoC を使用して一時的な IArticle コンポーネントとして解決を開始します。
たとえば、キャッスルでは次のようになります。<component id="ArticleEntity" service="IArticle" type="Article" lifestyle="transient" />
この後、拡張する必要がある場合は、次のように簡単になります。
public class MyArticle : Article
{
public string MyProperty { ..... }
}
あとは、構成を次のように変更するだけです。<component id="ArticleEntity" service="IArticle" type="Article" lifestyle="transient" />
したがって、問題のシステムを使用する人は誰でも、構成内の行を書き換えるだけで、すべてのクラスを置き換えることができます。新しいものは古いものと同じ機能を実装するため、他のすべてのエンティティも正しく機能します。
ところで、これは「関心の分離」哲学の良い解決策のようです。
私の質問は、これは正しいことですか? 真剣に考えた後、これを行うためのより良い方法を見つけることができませんでした。MEF も検討しましたが、プラグインを作成することを目的としているようですが、このようなシステムの既に完全な部分を置き換えたり拡張したりすることは目的ではないようです。
このトピックに関する多くの SO の質問 (およびその他の情報源) を読みましたが、最も注目すべきは次のとおり です。と IoC、コンテナをどこに置くのですか?
また、次のページで説明されている問題に陥っているのではないかと心配して い ます。 should-domain-entity-be-managed-by-ioc/
もう 1 つ: これにより、システム全体のテスト容易性が向上しますね。
どう思いますか?
EDIT:別のオプションは、これらのエンティティのファクトリーパターンを作成することですが、IoC.Resolve<IArticle>
より簡単ですIoC.Resolve<IArticleFactory>().CreateInstance()