我有几个与Rebus一起出现的新手问题。 Rebus ReadMe file中所有漂亮的样本都使用了温莎城堡,但我没有这个选项;相反,我必须使用Unity。
我的第一个挑战是为Unity IoC容器找到合适的适配器,例如:
var someContainerAdapter =
new AdapterForMyFavoriteIocContainer(myFavoriteIocContainer);
我终于找到了一些似乎可以完成工作的代码here,但也许存在更好的容器,因为我必须自己实现 IContainerAdapter 接口(我想知道是否需要它) ...)。
但我可以忍受......
我的下一个问题更糟,我还没有发现。在Rebus入门示例中,以下内容用于向IoC容器添加处理程序:
container.Register(
Component.For<IHandleMessages<DateTime>>()
.ImplementedBy<PrintDateTime>());
以上是Windsor Castle语法,我不知道Unity语法应该如何针对同一个动作。所以我需要一些帮助。如果我能够获得与Unity一起使用的小解决方案的建议,那么我将提出建议。
答案 0 :(得分:4)
我的建议是使用Rebus.Unity
,它是Rebus的现成Unity容器适配器,由一个很棒的Rebus贡献者制作。
有一个NuGet包,所以你可以只install-package Rebus.Unity
(或者你的首选方式将NuGet包添加到你的项目中。)
现在,为了向Unity注册处理程序,您应该意识到Unity 的行为与关于ResolveAll
行为的所有其他容器的行为不同(至少是我知道的,这要求所有处理程序都注册为命名注册。
我不记得确切的Unity语法来做到这一点,但我认为它看起来有点像这样:
container.RegisterType<IHandleMessages<SomeMessage>, MyMessageHandler>("id");
为了将MyMessageHandler
注册为SomeMessage
的处理程序。各种注册函数还有其他几个重载,所以你应该能够找到一个符合你需求的重载 - 但要记住与Unity,因为Rebus执行ResolveAll
,你必须始终注册处理程序一个键/ id 。
答案 1 :(得分:1)
与Rebus一起使用unity需要我注册以下类型的IHandleMessages
...自IContainerAdapter.GetHandlerInstancesFor&lt; T>用以上类型调用。
我担心不是这个想法。
我不能使用接口作为Key来统一解析类型,而不指定实现接口的类型。
如果一个令人敬畏的Rebus贡献者可以发布使用Unity的示例,那将是很棒的。
答案 2 :(得分:0)
如上所述,Unity只解析所请求的类型,它不会查找继承的类或接口。
如果你实现了一个使用反射来查找你所追求的实现的UnityExtension,那么有一种方法可以使用具有多态解析的Unity。我们需要一个Rebus适配器,用于统一的多态功能和方法Register&lt;&gt;和处理&lt;&gt;。
这是我们使用Unity的Rebus版本,它可以很好地工作。
公共类UnityContainerAdapter:IContainerAdapter,IDisposable
{
公共IBus巴士{get;内部集合; }
private readonly IUnityContainer _unityContainer;
private readonly IHandlerRegistrator _handlerRegistrator;
public UnityContainerAdapter(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
_handlerRegistrator = _unityContainer
.AddNewExtension<AllThatImplements>()
.Configure<IHandlerRegistrator>();
}
public IEnumerable<IHandleMessages> GetHandlerInstancesFor<T>()
{
return _unityContainer.ResolveAll<IHandleMessages<T>>();
}
public void Release(IEnumerable handlerInstances)
{
foreach (IDisposable disposable in handlerInstances.OfType<IDisposable>())
disposable.Dispose();
}
public void SaveBusInstances(IBus bus)
{
Bus = bus;
_unityContainer.RegisterInstance(typeof(IBus), bus);
_unityContainer.RegisterType<IMessageContext>(new InjectionMember[1]
{
new InjectionFactory(c => (object) MessageContext.GetCurrent())
});
}
public UnityContainerAdapter Register<THandler>()
{
_handlerRegistrator.RegisterImplementingType<THandler>(typeof(IHandleMessages<>));
return this;
}
public UnityContainerAdapter Handle<TMessage>(Action<TMessage> handler)
{
_unityContainer.RegisterType<IHandleMessages<TMessage>, HandlerMethodWrapper<TMessage>>(Guid.NewGuid().ToString(), new InjectionConstructor(handler));
return this;
}
internal class HandlerMethodWrapper<T> : IHandleMessages<T>
{
private readonly Action<T> _action;
public HandlerMethodWrapper(Action<T> action)
{
_action = action;
}
public void Handle(T message)
{
_action(message);
}
}
public void Dispose()
{
_unityContainer.Dispose();
}
#region - Unity Extionsion -
internal class AllThatImplements : UnityContainerExtension, IHandlerRegistrator
{
protected override void Initialize() { }
public void RegisterImplementingType<T>(Type implementationToLookFor)
{
var closedType = typeof(T);
closedType.GetInterfaces()
.Where(x => x.IsGenericType)
.Where(x => x.GetGenericTypeDefinition() == implementationToLookFor)
.ToList()
.ForEach(x => Container.RegisterType(x, closedType, Guid.NewGuid().ToString()));
}
}
internal interface IHandlerRegistrator : IUnityContainerExtensionConfigurator
{
void RegisterImplementingType<T>(Type inheritedTypeToLookFor);
}
#endregion
}