Предположим, что у меня есть интерфейс для службы:
public interface IFooService
{
void DoSomething();
}
И конкретная реализация этой службы, которая является общей:
public class FooService<TRequestingClass> : IFooService
{
public virtual void DoSomething() { }
}
И у меня есть другой класс, которому нужен экземпляр IFooService:
public class Bar
{
private IFooService _fooService;
public Bar(IFooService fooService)
{
this._fooService = fooService;
}
}
Мне нужно подключить мой контейнер IoC таким образом, чтобы при создании Bar он передавал аргумент конструктора FooService <Bar> . Есть много других классов, как Bar. Каждому может также понадобиться экземпляр FooService <TRequestingClass> переданный им, где TRequestingClass - тип класса, которому нужен экземпляр IFooService. Мне не нужно подвергать эту причудливость потребителям IFooService. Все, о чем они должны заботиться, это то, что они могут вызывать методы IFooService, которые они передали. Им не нужно знать, что конкретная реализация IFooService, которую они передали, требует чего-то особенного, чтобы быть построенным.
Приемлемая альтернатива FooService <T> будет неродским классом, который имеет строковый аргумент в своем конструкторе, который содержит имя класса, для которого он создается. то есть:
public class FooService : IFooService
{
public FooService(string requestingClassName) { }
}
Как подключить мой контейнер IoC для создания зависимости таким образом?
Если вы смущены, почему бы мне захотеть такой wierd-структуры, подумайте, как лучше работает log4net, когда вы получаете ILog, который создается с помощью log4net.LogManager.GetLogger(typeof (SomeClass)). Я не хочу заманивать свой код ссылками на log4net, поэтому я бы хотел написать простой интерфейс ILogger и реализовать его с чем-то вроде этого:
public class GenericLogger<T> : ILogger
{
private readonly ILog log;
public GenericLogger()
{
this.log = log4net.LogManager.GetLogger(typeof(T));
}
public void Debug(object message)
{
this.log.Debug(message);
}
/* .... etc .... */
}