2012-09-28 31 views
2

我有几个Rebus的新手启动问题。 Rebus ReadMe file中所有漂亮的样本都使用了温莎城堡,但我没有这个选择;相反,我必须使用Unity。使用Unity作为IoC的Rebus Servicebus

我的第一个挑战是找到一个统一的IoC容器合适的适配器,作为例子说:

var someContainerAdapter = 
    new AdapterForMyFavoriteIocContainer(myFavoriteIocContainer); 

我终于找到了一些代码here似乎做的工作,但也许更好的容器存在,因为我必须自己实现接口IContainerAdapter(我想知道是否需要......)。

但我可以忍受......

我的下一个问题,更糟糕的是,我还没有发现呢。在卤面入门 - 例如用于将处理程序添加到IoC容器如下:

container.Register(
    Component.For<IHandleMessages<DateTime>>() 
    .ImplementedBy<PrintDateTime>()); 

这上面是温莎城堡的语法和我不知道统一语法应如何对同样的动作。所以我需要一些帮助。一个建议是,如果我可以参考一个适用于Unity的小型解决方案。

回答

0

使用Unity与卤面要求我注册IHandleMessages以下类型

  • SubscriptionMessage
  • IRebusControlMessage
  • 对象

...因为IContainerAdapter.GetHandlerInstancesFor < T>被称为与上述类型。

而且我不害怕这个想法。

我不能使用接口作为Key来统一解析类型,也没有指定实现接口的类型。

如果真棒Rebus贡献者可以发布一个使用Unity的例子,那将是非常棒的。

+0

它不需要这些类型的处理程序 - 您的容器适配器可以自由地返回一个空序列的处理程序,如果您将'GetHandlerInstancesFor '直接委托给Unity的'ResolveAll ' – mookid8000

4

我的建议是使用Rebus.Unity,这是Rebus的一个现成的Unity容器适配器,由一个真棒Rebus贡献者制作。

它有一个NuGet包,所以你可以只install-package Rebus.Unity(或无论哪种方式是你的项目添加NuGet包的首选方式)。现在

,为了与统一登记处理程序,你应该知道的是统一表现比所有其他容器不同的事实在那里就ResolveAll行为(至少我所知道的那些),这需要您的所有处理程序都已注册为已命名的注册。

我不记得确切的统一语法要做到这一点,但我认为它看起来有点像这样:

container.RegisterType<IHandleMessages<SomeMessage>, MyMessageHandler>("id"); 

,以便注册MyMessageHandlerSomeMessage的处理程序。各种注册功能还有其他一些重载,所以您应该能够找到适合您需求的重载功能 - 但请记住,带有Unity的,因为Rebus执行ResolveAll,所以您必须始终注册具有密钥/编号的处理程序。

+0

谢谢你的提示。嗯......你是否真的说过,如果我可以摆脱Unity并使用Windsor.Castle,我可以省掉很多麻烦? –

+0

我现在正在尝试它,所以必须提及** Rebus.Unity **需要Microsoft.Practices.Unity的版本至少为2.1.505.0。 –

+0

我个人的偏好是温莎城堡,但Unity也可以。它与“ResolveAll”方面的其他IoC容器不同。 – mookid8000

0

如上所述,Unity只解析请求的类型,它不寻找继承的类或接口。

有一种方法可以使用Unity进行多态解析,但是如果你实现了一个UnityExtension来使用反射来找到你之后的实现。我们需要一个具有多态功能的统一的Rebus适配器,以及方法注册<>和处理<>。

这是我们使用Unity的Rebus版本,它很好地工作。

public class UnityContainerAdapter:IContainerAdapter,IDisposable {
public IBus Bus {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 

}