簡體   English   中英

如何以編程方式注冊依賴於Castle Windsor已注冊組件列表的組件?

[英]How to programmatically register a component that depends on a list of already registered components with Castle Windsor?

我正在以編程方式注冊一組都實現相同接口IRule的服務。 我還有另一個服務,看起來像這樣:

public class MyService {
    private IEnumerable<IRule> _rules;
    public MyService(IEnumerable<IRule> rules){
        _rules = rules;
    }
}

Hammett發布了一些我想要的東西, http://hammett.castleproject.org/?p=257 我將簽名更改為IRule [],並在帖子中嘗試了ArrayResolver技巧,但這對我不起作用(請注意,它也沒有破壞任何東西)。

任何人都知道如何以編程方式注冊一個組件,例如我上面發布的代碼嗎?

如果您不想更改MyService的簽名並繼續使用IEnumerable<IRule> ,則還可以創建一個自定義的ISubDependencyResolver。 那就是我們所做的:

public class EnumerableResolver : ISubDependencyResolver
{
    private readonly IKernel kernel;

    public EnumerableResolver(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
    {
        Type targetType = dependency.TargetType;
        if (targetType == null)
        {
            throw new ArgumentException("TargetType property cannot be null", "dependency");
        }

        if (targetType.IsGenericType && (targetType.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
        {
            Type service = targetType.GetGenericArguments()[0];
            return this.kernel.HasComponent(service);
        }
        return false;
    }

    public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
    {
        Type service = dependency.TargetType.GetGenericArguments()[0];
        Array array = this.kernel.ResolveAll(service, (IDictionary)null);
        return Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { service }), new object[] { array });
    }
}

它需要像這樣在容器中注冊:

container.Kernel.Resolver.AddSubResolver(new EnumerableResolver(this.Kernel));

我加載了Castle.MicroKernel的源代碼,注意到已經有一個ArrayResolver和ListResolver(在Castle.MicroKernel.Resolvers.SpecializedResolvers命名空間中)。 我從Hammet的博客(盲目地)復制的代碼無法正常工作,很可能是因為自編寫該框架以來,該框架已發生更改。

這是一個演示如何執行此操作的示例項目: http : //www.panteravb.com/downloads/WindsorCon.zip

我同時嘗試了ArrayResolver和ListResolver,它們都順利運行,這非常簡單,因此假設此服務類為:

public class MyService
{
    private IEnumerable<IRule> _rules;
    public MyService(IList<IRule> rules)
    {
        _rules = rules;
    }
}

您可以像這樣注冊此人:

private IWindsorContainer _container;
private void InitializeIoc()
{
    _container = new WindsorContainer();
    _container.Kernel.Resolver.AddSubResolver(new ListResolver(_container.Kernel));
    _container.Register(Component.For<IRule>().ImplementedBy<Rule1>());
    _container.Register(Component.For<IRule>().ImplementedBy<Rule2>());
    _container.Register(Component.For<MyService>());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM