依存性注入を実行していて、特定のインターフェイスの特別に型指定されたインスタンスを作成できる必要がある場合、推奨される解決策は、特別なファクトリクラスを作成することです。これにより、実際にコンテナを挿入しなくても、名前付き引数を使用できます。
例
これは、注入する抽象型です。
public interface ISerializerFactory
{
ISerializer GetSerializer(string name);
}
コンテナ(StructureMap)を利用する具体的なタイプは次のとおりです。
public class StructureMapSerializerFactory : ISerializerFactory
{
public ISerializer GetSerializer(string name)
{
return ObjectFactory.GetNamedInstance<ISerializer>(name);
}
}
その場合、クラスは次のようになります。
public class MyClass
{
private readonly ISerializerFactory serializerFactory;
public MyClass(ISerializerFactory serializerFactory)
{
if (serializerFactory == null)
throw new ArgumentNullException("serializerFactory");
this.serializerFactory = serializerFactory;
}
public string SerializeSomeData(MyData data)
{
ISerializer serializer = serializerFactory.GetSerializer("Json");
return serializer.Serialize(data);
}
}
自動的に機能しない「JsonSerializer」の代わりに、この通過する「Json」を作成しました。ただし、登録名を変更して、冗長な「Serializer」サフィックスを削除する必要があると思います(を要求しているため、これがシリアライザーであることがすでにわかっていますISerializer
)。つまり、次のようなメソッドを作成します。
private static string ExtractSerializerName(Type serializerType)
{
string typeName = serializerType.Name;
int suffixIndex = typeName.IndexOf("Serializer");
return (suffixIndex >= 0) ?
typeName.Substring(0, suffixIndex - 1) : typeName;
}
そして、次のように登録します。
scanner.AddAllTypesOf<ISerializer>().NameBy(type => ExtractSerializerName(type));
次に、「JsonSerializer」の代わりに文字列「Json」を使用して作成できます。これにより、見た目が少し醜くなり、結合が少なくなります。
ハードコードされた文字列が気に入らない場合は、ファクトリの列挙型を作成することもできます。
public enum SerializationFormat { Json, Bson, Xml };
public interface ISerializerFactory
{
ISerializer GetSerializer(SerializationFormat format);
}
public class StructureMapSerializerFactory : ISerializerFactory
{
public ISerializer GetSerializer(SerializationFormat format)
{
return ObjectFactory.GetNamedInstance<ISerializer>(format.ToString());
}
}
したがって、これを書く代わりに:
ISerializer serializer = serializerFactory.GetSerializer("Json");
代わりにこれを書くことができます:
ISerializer serializer =
serializerFactory.GetSerializer(SerializationFormat.Json);
長期的には、エラーが発生しにくくなります。
シリアライザーのクラス名を変更し始めたり、名前に一貫性がない場合は、単純なToString()
ものをswitch
ステートメントに置き換えて、実際に列挙値をクラス名にマップできるため、これはおそらく長期的にはより保守しやすくなります。再登録します。
おそらく、このコードのすべて(質問の自動登録コードを含む)を同じ名前空間、または同じコードファイルに入れて、これらの部分がすべて相互に依存していることを明確に示します。