首页 > 解决方案 > 在使用基于约定的注册时,如何使用类型化工厂来解析带参数的组件?

问题描述

Windsor 的文档说我们可以在TypedFactory方法调用中传递参数,这些参数将传递给工厂正在创建的类型的构造函数:

您还可以使用从调用者获取参数的方法来解析组件。您传入的参数将被传递到容器的解析管道。

使用基于约定的注册时,这是如何工作的?在验证没有缺少组件并且我的配置正确时出现异常,说我要传递给构造函数的类型尚未注册。

例如,采用以下代码:

public interface IWatcherFactory : IDisposable
{
    IWatcher GetWatcher(ImportTarget importTarget);
}

这是注册的container.Register(Component.For<IWatcherFactory>().AsFactory());

public class FolderWatcher : WatcherBase
{
    public FolderWatcher(ImportTarget importTarget, ILogger logger, IClock clock, IFileSystem fileSystem)
        : base(importTarget, logger)
    {
        // ...
    }
}

WatcherBase在哪里

public abstract class WatcherBase : IWatcher
{
    public WatcherBase(ImportTarget importTarget, ILogger logger)
    {
        // ...
    }
}

注册的container.Register(Classes.FromThisAssembly().BasedOn<IWatcher>().WithServiceAllInterfaces().LifestyleTransient());

现在其他问题和答案参数名称需要匹配才能工作,我的已经这样做了。

这是我得到的确切错误:

'FolderWatcher' is waiting for the following dependencies:
- Service 'ImportTarget' which was not registered.

我认为问题在于没有任何东西告诉温莎由于公约注册而存在依赖ImportTarget,但我不能确定。

我还有一个组件选择器,如下所示:

public class WatcherFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
    protected override string GetComponentName(MethodInfo method, object[] arguments)
    {
        var config = arguments.FirstOrDefault() as ImportTarget;
        if (config == null)
        {
            return base.GetComponentName(method, arguments);
        }

        return config.WatcherFullyQualifiedName;
    }
}

这是这样注册的:container.Register(Component.For<ITypedFactoryComponentSelector>().ImplementedBy<WatcherFactoryComponentSelector>());

标签: c#dependency-injectioninversion-of-controlcastle-windsorconventions

解决方案


所以这个问题涵盖了两个相关但独立的主题。我会依次回答他们。

为什么温莎抱怨缺少ImportTarget依赖?

这与您注册组件的方式没有任何关系,无论是按照惯例,一一注册还是(请不要)使用 XML。

请记住,Windsor 在安全方面犯了错误,它并不认为您只会FolderWatcher通过使用类型化工厂方法获得对 的依赖。它尝试使用它所拥有的东西——也就是说,它查看它所知道的组件,并在意识到它没有一个组件时,ImportTarget它会产生这个消息。

请注意,这不是错误,而是更多的警告。它的存在是为了让你注意这样一个事实,即如果你试图直接依赖它FolderWatcher,你就会失败。

现在(参考您自己的答案),注册 aComponent.For<ImportTarget>()将使 Windsor 闭嘴,但我猜(没有看到您的其余代码)一个普通的ImportTarget,就像您得到的那样new ImportTarget()不是很有用,没有WatcherFullyQualifiedName正确设置。所以这是掩盖问题而不是解决问题。

将组件选择器连接到类型化工厂的正确方法是什么?

这很容易——你在这里做对了。就个人而言,除非您将它用于其他地方的其他工厂,否则我什至不会费心WatcherFactoryComponentSelector在容器中注册,但是 go .AsFactory(cfg => cfg.SelectedWith(new WatcherFactoryComponentSelector())),但这是一个小问题。


推荐阅读