Ответ 1
Простой инжектор не имеет этого интерфейса factory. Идея заключается в том, что при правильном применении Injection Dependency необходимость использования заводов минимизируется, что делает полезность такой функции ограниченной.
В Simple Injector вам нужно написать реализацию самостоятельно, но это обычно тривиально. Пример:
private sealed class SimpleInjectorBarFactory : IBarFactory {
private readonly Container container;
public SimpleInjectorBarFactory(Container container) {
this.container = container;
}
public Bar CreateBar() {
return this.container.GetInstance<Bar>();
}
}
Этот класс можно зарегистрировать следующим образом:
container.RegisterSingleton<IBarFactory, SimpleInjectorBarFactory>();
Или, если вы ленивы, вы можете зарегистрировать Func<Bar>
для инъекции следующим образом:
container.RegisterSingleton<Func<Bar>>(() => container.GetInstance<Bar>());
Обратите внимание, что поскольку эта реализация SimpleInjectorBarFactory
зависит от экземпляра Container
, она должна быть частью Root of Composition, чтобы предотвратить использование Контейнер как Сервис-локатор. Помещая классы внутри вашего корня композиции, он становится просто частью инфраструктуры.
Таким образом, функция исключается специально, но библиотека может быть продлена достаточно легко, чтобы это можно было с ограниченным количеством кода:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
public static class AutomaticFactoryExtensions {
public static void RegisterFactory<TFactory>(this Container container) {
if (!typeof(TFactory).IsInterface)
throw new ArgumentException(typeof(TFactory).Name + " is no interface");
container.ResolveUnregisteredType += (s, e) => {
if (e.UnregisteredServiceType == typeof(TFactory)) {
e.Register(Expression.Constant(
value: CreateFactory(typeof(TFactory), container),
type: typeof(TFactory)));
}
};
}
private static object CreateFactory(Type factoryType, Container container) {
var proxy = new AutomaticFactoryProxy(factoryType, container);
return proxy.GetTransparentProxy();
}
private sealed class AutomaticFactoryProxy : RealProxy {
private readonly Type factoryType;
private readonly Container container;
public AutomaticFactoryProxy(Type factoryType, Container container)
: base(factoryType) {
this.factoryType = factoryType;
this.container = container;
}
public override IMessage Invoke(IMessage msg) {
if (msg is IMethodCallMessage) {
return this.InvokeFactory(msg as IMethodCallMessage);
}
return msg;
}
private IMessage InvokeFactory(IMethodCallMessage msg) {
if (msg.MethodName == "GetType")
return new ReturnMessage(this.factoryType, null, 0, null, msg);
if (msg.MethodName == "ToString")
return new ReturnMessage(this.factoryType.Name, null, 0, null, msg);
var method = (MethodInfo)msg.MethodBase;
object instance = this.container.GetInstance(method.ReturnType);
return new ReturnMessage(instance, null, 0, null, msg);
}
}
}
Используя вышеописанный метод расширения, вы можете сделать регистрацию для factory способом, очень похожим на регистрацию Ninject:
container.RegisterFactory<IBarFactory>();
Что это.