どのように工場内でコンストラクタ・インジェクションを実装していますか?
-
22-08-2019 - |
質問
、どのように実行時にコンストラクタへの依存性を注入しますか?
私は、異なるフォーマットでFOOSを構築しています - 私たちはFooのためのさまざまな用途を見つけるようブール、配列、FREETEXT、行列など、そのフォーマットのリストが成長します。ここに私の基本的なコアドメインがあります:
public interface IFoo
{
FooFormat Format { get; }
}
public class Foo : IFoo
{
private FooFormat _format;
internal Foo(FooFormat format)
{
_format = format;
}
public FooFormat Format { get { return _format; } }
}
public abstract class FooFormat
{
}
public class DefaultFooFormat : FooFormat
{
}
public class BooleanFooFormat : FooFormat
{
public IList<bool> Values { get; set; }
}
public class ArrayFooFormat : FooFormat
{
private IList<string> _values;
public ArrayFooFormat(IList<string> values)
{
_values = values;
}
public IList<string> Values { get { return _values; } }
}
IFooは、消費者の文脈のために飾られます:
public abstract class FooDecorator : IFoo
{
private IFoo _foo;
protected FooDecorator(IFoo foo)
{
_foo = foo;
}
public FooFormat Format
{
get { return _foo.Format; }
}
protected IFoo foo
{
get { return _foo; }
}
}
私は、消費者が直接のFooのインスタンスを作成する必要はありませんので、私は工場を使用するように強制します:
public abstract class FooFactory
{
protected IFoo Build<T>()
{
FooFormat format = GetFormat<T>();
return new Foo(format);
}
private FooFormat GetFormat<T>()
{
if (typeof(T) == typeof(ArrayFooFormat)) return new ArrayFooFormat(new List<string>());
if (typeof(T) == typeof(BooleanFooFormat)) return new BooleanFooFormat();
return new DefaultFooFormat();
}
}
そしてその後も、彼らは特定のコンテキストのための私の抽象工場から工場を導出する必要があります。
私は特にそうのように、HTMLのコンテキストでFOOSを構築しています
public class HtmlFoo : FooDecorator
{
public HtmlFoo(IFoo foo) : base(foo) { }
public string ToHtml()
{
return "<div>" + this.Format.ToString() + "</div>";
}
}
public class HtmlFooFactory : FooFactory
{
public IFoo BuildFoo<T>()
{
IFoo foo = Build<T>();
return new HtmlFoo(foo);
}
}
public class HtmlFooConsumer
{
public void DoSomeFoo()
{
var factory = new HtmlFooFactory();
var htmlBooleanFoo = factory.BuildFoo<BooleanFooFormat>();
var htmlArrayFoo = factory.BuildFoo<ArrayFooFormat>();
}
}
私の問題は、私の抽象FooFactoryである:私はいつも私のArrayFooFormatに空の値の一覧を注入しています。私は消費者からの値のリストを渡すことができるようにしたいです。他のFooFormatsのために、私は消費者から右側のコンストラクタの引数に渡したいです。しかし、私は死んでシンプルなパブリックAPIを維持したい - 私はBuildFoo()のオーバーロードの束をしたくない
。それでは、どのように私はHtmlFooConsumer.DoSomeFoo(内側からfactory.BuildFoo
解決
たぶん、あなたはあなたの抽象FooFormatがIFooFormatになり、一般的なFooFormatは、パラメータを渡さInitメソッドを提供し、これらの線に沿って何かを行うことができます。
[ビルドの単一の過負荷は、パラメータを渡すことができます。
public interface IFooFormat
{
}
public class FooFormat<TValue> : IFooFormat
{
private TValue _value;
public void Init(TValue value)
{
_value = value;
}
public TValue Value
{
get { return _value; }
}
}
public class ArrayFooFormat : FooFormat<IList<string>> { }
public class BooleanFooFormat : FooFormat<bool> { }
public class DefaultFooFormat : IFooFormat { }
public interface IFoo { }
public class Foo : IFoo
{
private IFooFormat _format;
internal Foo(IFooFormat format)
{
_format = format;
}
public IFooFormat Format { get { return _format; } }
}
public class FooFactory
{
protected IFoo Build<TFormat, TArg>(TArg arg) where TFormat : FooFormat<TArg>, new()
{
TFormat format = new TFormat();
format.Init(arg);
return new Foo(format);
}
protected IFoo Build<TFormat>() where TFormat : IFooFormat, new()
{
return new Foo(new TFormat());
}
}
他のヒント
工場は基本的に静的変数のオブジェクト指向バージョンです。私は1つalltogetherの使用を避けると思います。代わりに工場を使用するようにクライアントを強制するのは、おそらくあなたは、単に工場の必要性をsidestepping、そのコンストラクタにオブジェクトを挿入することができます。