简单注入器注入 IEnumerable<Func<T>>
Simple Injector Inject IEnumerable<Func<T>>
如何使用 Simple Injector 注入 IEnumerable<Func<T>>
?
只是为了添加一些上下文,我正在尝试创建所有知道如何处理一个特定事件的事件处理程序。这是我的 Container
注册:
container.RegisterCollection(typeof(IHandleDomainEvent<>),
AppDomain.CurrentDomain.GetAssemblies());
这里有两个 类 实现了同一事件的 IHandleEvent<T>
接口:
public class Reservation : IHandleDomainEvent<OrderConfirmed>{}
public class Order: IHandleDomainEvent<OrderConfirmed>{}
所以当我调用 Simple Injector 时:
var handlers = _container.GetAllInstances<Func<IHandleDomainEvent<OrderConfirmed>>>();
我想收到IEnumerable<Func<IHandleDomainEvent<OrderConfirmed>>>
澄清一下,我知道如果我调用:
var handlers = _container.GetAllInstances<IHandleDomainEvent<OrderConfirmed>>();
我会得到一个IEnumerable<IHandleDomainEvent<OrderConfirmed>>
。
对于只有一种实现的接口,注册使用:
container.Register(typeof(IHandleDomainEvent<>),
AppDomain.CurrentDomain.GetAssemblies(), Lifestyle.Scoped);
并在注册末尾添加如下ResolveUnregisteredType:
container.ResolveUnregisteredType += (o, args) => ResolveFuncOfT(o, args, container);
// Function
private static void ResolveFuncOfT(object s, UnregisteredTypeEventArgs e, Container container)
{
var type = e.UnregisteredServiceType;
if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func<>)) return;
Type serviceType = type.GetGenericArguments().First();
InstanceProducer producer = container.GetRegistration(serviceType, true);
Type funcType = typeof(Func<>).MakeGenericType(serviceType);
var factoryDelegate = Expression.Lambda(funcType, producer.BuildExpression()).Compile();
e.Register(Expression.Constant(factoryDelegate));
}
将允许调用:
var handler = _container.GetInstance<Func<IHandleDomainEvent<TEvent>>>();
这就是 Simple Injector 的优点:您永远不必解析 IEnumerable<Func<T>>
,因为任何由 Simple Injector 解析的 IEnumerable<T>
已经作为 stream.
这意味着当您解析 IEnumerable<T>
时,流中的 none 元素将被解析。它们仅在迭代可枚举时得到解决,并得到解决 one-by-one.
迭代流时,元素将根据其生活方式进行解析。这意味着当集合中的元素 Transient
迭代流两次将导致创建新的瞬态实例。
示例:
// Only resolves the enumerable, not the contained handlers.
// This enumerable itself is a singleton, you can reference it forever.
var collection = container.GetInstances<IEventHandler<OrderConfirmed>>();
// Calls back into the container to get the first element, but nothing more
var first = collection.First();
// Since the stream that Simple Injector returns is a IList<T>, getting the last
// element is an O(1) operation, meaning that only the last element is resolved;
// not the complete collection.
var last = collection.Last();
// Calling .ToArray(), however, will obviously resolve all registrations that are
// part of the collection.
var all = collection.ToArray();
// Iterating a stream will always call back into the container, which ensures
// that the stream adheres to the elements lifestyles. Transients will be
// created on each iteration, while singletons will only be created once.
container.Register<Apple>(Lifestyle.Transient);
container.Register<Banana>(Lifestyle.Singleton);
container.RegisterCollection<IFruit>(typeof(Apple), typeof(Banana));
var fruits = container.GetAllInstances<IFruit>();
Assert.AreNotSame(fruits.First(), fruits.First());
Assert.AreSame(fruits.Last(), fruits.Last());
// Even other collection types such as IReadOnlyCollection<T> behave as streams
var col = container.GetInstance<IReadOnlyCollection<IEventHandler<OrderConfirmed>>();
// This gives you the possibility to get a particular item by its index.
var indexedItem = col[3];
您可以在此处找到有关在 Simple Injector 中使用集合的更多信息:
如何使用 Simple Injector 注入 IEnumerable<Func<T>>
?
只是为了添加一些上下文,我正在尝试创建所有知道如何处理一个特定事件的事件处理程序。这是我的 Container
注册:
container.RegisterCollection(typeof(IHandleDomainEvent<>),
AppDomain.CurrentDomain.GetAssemblies());
这里有两个 类 实现了同一事件的 IHandleEvent<T>
接口:
public class Reservation : IHandleDomainEvent<OrderConfirmed>{}
public class Order: IHandleDomainEvent<OrderConfirmed>{}
所以当我调用 Simple Injector 时:
var handlers = _container.GetAllInstances<Func<IHandleDomainEvent<OrderConfirmed>>>();
我想收到IEnumerable<Func<IHandleDomainEvent<OrderConfirmed>>>
澄清一下,我知道如果我调用:
var handlers = _container.GetAllInstances<IHandleDomainEvent<OrderConfirmed>>();
我会得到一个IEnumerable<IHandleDomainEvent<OrderConfirmed>>
。
对于只有一种实现的接口,注册使用:
container.Register(typeof(IHandleDomainEvent<>),
AppDomain.CurrentDomain.GetAssemblies(), Lifestyle.Scoped);
并在注册末尾添加如下ResolveUnregisteredType:
container.ResolveUnregisteredType += (o, args) => ResolveFuncOfT(o, args, container);
// Function
private static void ResolveFuncOfT(object s, UnregisteredTypeEventArgs e, Container container)
{
var type = e.UnregisteredServiceType;
if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func<>)) return;
Type serviceType = type.GetGenericArguments().First();
InstanceProducer producer = container.GetRegistration(serviceType, true);
Type funcType = typeof(Func<>).MakeGenericType(serviceType);
var factoryDelegate = Expression.Lambda(funcType, producer.BuildExpression()).Compile();
e.Register(Expression.Constant(factoryDelegate));
}
将允许调用:
var handler = _container.GetInstance<Func<IHandleDomainEvent<TEvent>>>();
这就是 Simple Injector 的优点:您永远不必解析 IEnumerable<Func<T>>
,因为任何由 Simple Injector 解析的 IEnumerable<T>
已经作为 stream.
这意味着当您解析 IEnumerable<T>
时,流中的 none 元素将被解析。它们仅在迭代可枚举时得到解决,并得到解决 one-by-one.
迭代流时,元素将根据其生活方式进行解析。这意味着当集合中的元素 Transient
迭代流两次将导致创建新的瞬态实例。
示例:
// Only resolves the enumerable, not the contained handlers.
// This enumerable itself is a singleton, you can reference it forever.
var collection = container.GetInstances<IEventHandler<OrderConfirmed>>();
// Calls back into the container to get the first element, but nothing more
var first = collection.First();
// Since the stream that Simple Injector returns is a IList<T>, getting the last
// element is an O(1) operation, meaning that only the last element is resolved;
// not the complete collection.
var last = collection.Last();
// Calling .ToArray(), however, will obviously resolve all registrations that are
// part of the collection.
var all = collection.ToArray();
// Iterating a stream will always call back into the container, which ensures
// that the stream adheres to the elements lifestyles. Transients will be
// created on each iteration, while singletons will only be created once.
container.Register<Apple>(Lifestyle.Transient);
container.Register<Banana>(Lifestyle.Singleton);
container.RegisterCollection<IFruit>(typeof(Apple), typeof(Banana));
var fruits = container.GetAllInstances<IFruit>();
Assert.AreNotSame(fruits.First(), fruits.First());
Assert.AreSame(fruits.Last(), fruits.Last());
// Even other collection types such as IReadOnlyCollection<T> behave as streams
var col = container.GetInstance<IReadOnlyCollection<IEventHandler<OrderConfirmed>>();
// This gives you the possibility to get a particular item by its index.
var indexedItem = col[3];
您可以在此处找到有关在 Simple Injector 中使用集合的更多信息: