Windsor - 装饰所有找到的实现

时间:2017-06-11 16:48:37

标签: c# decorator castle-windsor

我有一个获取数据的接口IGetter<IEvent>,它有几个实现(每个实现从其他类型的源获取数据)。此接口是通用的,因为它的实现可以返回不同类型的事件(SourceEventStatisticsEvent,但都基于IEvent接口)。

这是一个示例代码(隐藏的详细信息使帖子更短 - LINQPad的完整工作演示是here)。装饰器正在注册,但尚未解决。只解析了普通Getters,没有记录和缓存功能。

我应该如何注册此代码才能使装饰器工作?

// An interface defining an event, "something happened at time When"
public interface IEvent { DateTime When { get; set; }}
// They come from a number of sources (e.g. Windows Event Log, sent e-Mails, disk activity, actions logged in issue tracker etc.)
public class SourceEvent     : IEvent { public DateTime When { get; set; } public string What { get; set; }}
// Some implementations:
public class MailEvent       : SourceEvent { }
public class FileEvent       : SourceEvent { }
// List of all events returned from all implemented sources will be ultimately calculated into activity level at any given time
public class StatisticsEvent : IEvent { public DateTime When { get; set; } public int HowMany{ get; set; }}


// An interface for a class capable of reading IEvents from one source
public interface IGetter<TData> where TData : IEvent { /*...*/ }
// Some implementations
public class MailGetter       : IGetter<MailEvent> { /*...*/ }
public class FileGetter       : IGetter<FileEvent> { /*...*/ }
// Implementation of this is also based on IGetter (but it gets data from all other IGetters - simplified in this example)
public class StatisticsGetter : IGetter<StatisticsEvent> { /*...*/ }


// Decorators for IGetters - all the magical things I want Getters to be able do
public class Cache<TData>  : IGetter<TData> where TData : IEvent { /*...*/ }
public class Logger<TData> : IGetter<TData> where TData : IEvent { /*...*/ }


void Main(string[] args)
{
    // Dependency Injection registration
    var ioc = new WindsorContainer();
    ioc.Register(
        Component.For(typeof(IGetter<>)).ImplementedBy(typeof(Cache<>)),
        Component.For(typeof(IGetter<>)).ImplementedBy(typeof(Logger<>)), // Decorators registered here are not being injected
        Classes.FromThisAssembly()
            .BasedOn(typeof(IGetter<>))
            .WithServiceBase() // Getters for all sources are registered fine
    );

    var source1 = ioc.Resolve<IGetter<MailEvent>>();
    source1.Query().Dump("Source 1 - \"Querying mails\"");
    source1.Query().Dump("Source 1 - \"From cache\""); // Doesn't read from cache, instead it queries again

    var source2 = ioc.Resolve<IGetter<FileEvent>>();
    source2.Query().Dump("Source 2 - \"Querying files\"");
    source2.Query().Dump("Source 2 - \"From cache\"");

    var stats = ioc.Resolve<IGetter<StatisticsEvent>>(); // All implementations of IGetter and all implementations of IEvent must be successfully resovled
    stats.Query().Dump("Statistics - \"Querying stats\"");
    stats.Query().Dump("Statistics - \"From cache\"");

//  This works, but we need Windsor to do it for us
    //  var manual = new Cache<MailEvent>(new Logger<MailEvent>(new MailGetter()));
    //  manual.Query().Dump("Manual - \"Querying mails\"");
    //  manual.Query().Dump("Manual - \"From cache\"");
}

1 个答案:

答案 0 :(得分:0)

你正在以相当自以为是的方式遇到Castle Windsor确定解决依赖关系的顺序和优先级。

因为你有一个开放的通用注册,或者你有两个,但也有大量的具体类型注册,它将优先考虑具体的实现。

如何解决这个问题有几种思路。

所有通用类型装饰器的手动显式注册

ioc.Register(
    Component.For<IGetter<MailEvent>>().ImplementedBy<Logger<MailEvent>>(),
    Component.For<IGetter<FileEvent>>().ImplementedBy<Logger<FileEvent>>(),
    Component.For<IGetter<StatisticsEvent>>().ImplementedBy<Logger<StatisticsEvent>>(),

    Component.For<IGetter<MailEvent>>().ImplementedBy<Cache<MailEvent>>(),
    Component.For<IGetter<FileEvent>>().ImplementedBy<Cache<FileEvent>>(),
    Component.For<IGetter<StatisticsEvent>>().ImplementedBy<Cache<StatisticsEvent>>(),

    Classes.FromThisAssembly()
                       .BasedOn(typeof(IGetter<>))
                       .WithServiceBase() // Getters for all sources are registered fine
            );

缺点是忘记注册另一个装饰器变得非常容易,但它会起到作用。

拦截器(根据documentation
您的里程可能因此而异,因为这些有效地代表您的实施并在执行之前或之后采取行动。他们有点像装饰者,但不是纯粹意义上的。

根据接受的答案here,处理ISubDependencyResolver 的实施。