ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C#-简单注入器注入IEnumerable>

2019-10-25 08:05:13  阅读:203  来源: 互联网

标签:dependency-injection c expression-trees simple-injector


如何注入IEnumerable< Func< T>使用简单注射器?

仅添加一些上下文,我试图创建所有知道如何处理一个特定事件的EventHandlers.这是我的容器注册:

container.RegisterCollection(typeof(IHandleDomainEvent<>),
    AppDomain.CurrentDomain.GetAssemblies());

这里是实现IHandleEvent< T>的两个类.相同事件的界面:

public class Reservation : IHandleDomainEvent<OrderConfirmed>{}
public class Order: IHandleDomainEvent<OrderConfirmed>{}

因此,当我调用简单注入器时:

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>>.因为任何IEnumerable< T>由Simple Injector解决的问题已充当流.

这意味着,当您解析IEnumerable< T>时,将不会解析该流的任何元素.它们仅在迭代可枚举时得到解决,并且被一对一解决.

迭代流时,将根据元素的生活方式对其进行解析.这意味着当集合中的元素为瞬态时,对流进行两次迭代将导致创建新的瞬态实例.

例:

// 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 Documentation – Using – Collection types
> Simple Injector Documentation – Advanced – Auto-Registration
> Simple Injector Documentation – Design Decisions –
The API clearly differentiates the registration of collections

标签:dependency-injection,c,expression-trees,simple-injector
来源: https://codeday.me/bug/20191025/1927137.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有