3

我正在按照本文档使用类型化工厂并将参数传递给构造函数。当我尝试传递 2 个参数(1,“fo”)时,类型化工厂给了我这个错误,如代码所示。

在此处输入图像描述

public class SomeClass {
    public ITypedFactory2 F2 { get; set; } 
    public void SomeFunction() {
        var req = F2.Create<IGetFooRequest>(1, "fo"); // ERROR HERE
    }
}
public class GetFooRequest : IGetFooRequest {
    public int Bar { get; private set; }
    public string Ton { get; private set; }
    public GetFooRequest(int bar, string ton ) {
        Bar = bar;
        Ton = ton;
    }
}
public interface IGetFooRequest{
    int Bar { get; }
    string Ton { get; }
}    
public interface ITypedFactory2 {
    T Create<T>(int param1, string param2);
    void Release(object t);
}

这是温莎安装程序部分...

container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactory2>().AsFactory());
container.Register(AllTypes
            .FromAssemblyContaining<IGetFooRequest>()
            .Where(type => type.Name.EndsWith("Request"))
            .WithService.AllInterfaces().LifestyleTransient());

为什么它说无法解决非可选依赖...?我通过了 (1,"fo"); 我真的不明白为什么会这样......请帮忙。

4

3 回答 3

8

我有同样的问题,只是想出了答案。工厂方法的参数名称和类构造函数的参数名称必须匹配,不区分大小写。

所以将您的工厂界面更改为

public interface ITypedFactory2 {
    T Create<T>(int **bar**, string **ton**);
    void Release(object t);
}

或你的班级

public class GetFooRequest : IGetFooRequest {
    public int Bar { get; private set; }
    public string Ton { get; private set; }
    public GetFooRequest(int **param1**, string **param2**) {
        Bar = bar;
        Ton = ton;
    }
}
于 2013-07-24T21:51:39.370 回答
2

我查看了自己的代码并说,(int param1, string param2) 看起来不太好。让我使用 (int bar, string ton) ... 这个命名解决了这个问题。LoL 难以置信,我没有看到那个文件提到命名的重要性。

幸运的是,我确实记得这里的介绍说依赖项首先按名称解析,然后按类型解析。这就是按名称部分工作,按类型部分进入水中。无论如何,我很高兴我知道如何使用它,所以我在这里与需要它的人分享我的答案。

于 2012-07-29T07:01:45.520 回答
1

如果您想通过类型而不是参数名称来解析,您可以创建自己的ComponentSelector

public class ComponentSelector : DefaultTypedFactoryComponentSelector
{
    protected override Arguments GetArguments(MethodInfo method, object[] arguments)
    {
        if (arguments == null)
            return null;

        Arguments argumentMap = new Arguments();
        ParameterInfo[] parameters = method.GetParameters();

        List<Type> types = parameters.Select(p => p.ParameterType).ToList();
        List<Type> duplicateTypes = types.Where(t => types.Count(type => type == t) > 1).ToList();

        for (int i = 0; i < parameters.Length; i++)
        {
            if (duplicateTypes.Contains(parameters[i].ParameterType))
                argumentMap.Add(parameters[i].Name, arguments[i]);
            else
                argumentMap.Add(parameters[i].ParameterType, arguments[i]);
        }

        return argumentMap;
    }
}

正如您在我的实现中看到的那样,您需要处理构造函数具有多个具有相同类型的参数的情况。
在这种情况下,您必须按参数名称解​​析,因为Castle.Windsor将为具有相同类型的每个参数使用类型的第一个参数。

要使用您自己的ComponentSelector,您还必须在您的网站上注册IWindsorContainer

container.Register(Component.For<ComponentSelector, ITypedFactoryComponentSelector>());

最后你必须告诉你的工厂使用你自己的ComponentSelector作为它的组件选择器:

container.Register(Component.For<ITypedFactory2>().AsFactory(f => f.SelectedWith<ComponentSelector>()));

有关更多信息,请查看有关如何使用自定义组件选择器的官方文档。

于 2019-04-10T15:30:27.413 回答