使用Unity作为IoC的Rebus Servicebus

时间:2012-09-28 08:26:46

标签: c# dependency-injection unity-container servicebus rebus

我有几个与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一起使用的小解决方案的建议,那么我将提出建议。

3 个答案:

答案 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

  • SubscriptionMessage
  • IRebusControlMessage
  • 物体

...自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

}