c# – 介体模式和简单注入器的逆变
作者:互联网
这个问题起源于我正在尝试为MediatR:https://github.com/jbogard/MediatR/pull/14创建一个简单的注入器实现.
我在尝试解决通用处理程序接口的实现时遇到了麻烦.考虑以下通知处理程序接口:
public interface INotificationHandler<in TNotification>
where TNotification : INotification
{
void Handle(TNotification notification);
}
INotifcation只是一个空的标记界面.
我为Pinged(实现INotification)事件定义了以下处理程序:
public class PingedHandler : INotificationHandler<Pinged>
{
public void Handle(Pinged notification) { }
}
public class PingedHandler2 : INotificationHandler<Pinged>
{
public void Handle(Pinged notification) { }
}
还有一个通用的处理程序(注意这应该处理每个INotification):
public class GenericHandler : INotificationHandler<INotification>
{
public void Handle(INotification notification) { }
}
通过以下注册:
var container = new Container();
container.RegisterManyForOpenGeneric(
typeof (INotificationHandler<>),
(service, impls) => container.RegisterAll(service, impls),
AppDomain.CurrentDomain.GetAssemblies());
现在我期待:
GetAllInstances<INotificationHandler<Pinged>>();
解决它所做的PingedHandler和PingedHandler2.但它没有解析GenericHandler,因为它实现了INotificationHandler< INotification>而不是INotificationHandler< Pinged>.我想知道是否有办法让Simple Injector搜索整个对象图并解决任何Pinged.
我从史蒂文发现了a blog post关于协方差和反方差的问题,但是我无法让它适用于我的例子.
解决方法:
UPDATE
从Simple Injector版本开始,2.7 this functionality现已成为标准配置,您不再需要下面显示的解决方法.
您缺少该文章中描述的MultipleDispatchEventHandler的变体.采用基本逻辑并将其应用于抽象确实可以得到您期望的结果:
[Fact]
public void RegisterAll_Contravariant_Succeeds()
{
var container = new Container();
container.RegisterManyForOpenGeneric(
typeof(INotificationHandler<>),
(service, impls) => container.RegisterAll(service, impls),
AppDomain.CurrentDomain.GetAssemblies());
var handlersType = typeof(IEnumerable<INotificationHandler<Pinged>>);
var handlersCollection = (
from r in container.GetCurrentRegistrations()
where handlersType.IsAssignableFrom(r.ServiceType)
select r.GetInstance())
.Cast<IEnumerable<INotificationHandler<Pinged>>>()
.ToArray();
var result =
from handlers in handlersCollection
from handler in handlers
select handler;
Assert.Equal(3, result.Count());
}
但是使GenericHandler变得通用可能更容易:
public class GenericHandler<TNotification> : INotificationHandler<TNotification>
where TNotification : INotification
{
public void Handle(TNotification notification) { }
}
提供更简单的注册
[Fact]
public void RegisterAll_WithOpenAndClosedGenerics_Succeeds()
{
var container = new Container();
var types = OpenGenericBatchRegistrationExtensions
.GetTypesToRegister(
container,
typeof(INotificationHandler<>),
AccessibilityOption.AllTypes,
AppDomain.CurrentDomain.GetAssemblies())
.ToList();
types.Add(typeof(GenericHandler<>));
container.RegisterAll(typeof(INotificationHandler<>), types);
var result = container.GetAllInstances<INotificationHandler<Pinged>>().ToList();
Assert.Equal(3, result.Count());
}
标签:c,simple-injector,mediator,mediatr 来源: https://codeday.me/bug/20190609/1206252.html