Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用castle windsor将运行时参数传递给以前注册的工厂方法?_C#_.net_Castle Windsor_Castle - Fatal编程技术网

C# 如何使用castle windsor将运行时参数传递给以前注册的工厂方法?

C# 如何使用castle windsor将运行时参数传递给以前注册的工厂方法?,c#,.net,castle-windsor,castle,C#,.net,Castle Windsor,Castle,我有一个使用Castle Windsor的报告MVC应用程序 在应用程序启动时(在global.asax中),所有类型都会被注册,然后对应用程序的每个后续请求都会解析相关的报告类型,windsor会自动处理依赖项 我需要根据请求中传入的参数,将一个依赖类型切换为另一个依赖类型 我怎样才能做到这一点 我已向windsor注册了一个factory方法来处理可切换类型的解析,但由于这是在应用程序启动时注册的,当参数仅在以后的请求中可用时,我如何将参数传递给factory方法 如果我尝试为每个请求注册工

我有一个使用Castle Windsor的报告MVC应用程序

在应用程序启动时(在global.asax中),所有类型都会被注册,然后对应用程序的每个后续请求都会解析相关的报告类型,windsor会自动处理依赖项

我需要根据请求中传入的参数,将一个依赖类型切换为另一个依赖类型

我怎样才能做到这一点

我已向windsor注册了一个factory方法来处理可切换类型的解析,但由于这是在应用程序启动时注册的,当参数仅在以后的请求中可用时,我如何将参数传递给factory方法


如果我尝试为每个请求注册工厂,它会在第一个请求上工作,但随后会在所有请求上抱怨工厂已注册。在每次请求后注销工厂听起来不是正确的做法。

当您需要在运行时解析类型时,通常的解决方案是注入一个工厂,该工厂可以在适当的时间做出决定:

public class ReportFactory: IReportFactory {
    IReport CreateReport(bool useDefault) {
        if (useDefault) {
            return new DefaultReport();
        } else {
            return new UnusualReport();
        }
    }
}

以前需要
IReport
的类应该要求使用
IReportFactory

您肯定不想根据每个请求修改容器。这是灾难的秘诀

你有两个选择。第一种方法是在工厂方法中使用HttpContext.Current

IWhatever CreateWhatever() {
     if (HttpContext.Current.Request["parameter"] == "value-for-other-whatever")
       return new FirstWhatever();

     return DefaultWhatever();
}
另一个(更好的)选项是注入一个解析正确实现的工厂类型,而不是让容器为您执行

public class WhateverFactory : IWhateverFactory {
     public IWhatever GetWhatever(string parameter) {
         if(parameter == "value for other whatever")
            return new OtherWhatever();

         return new DefaultWhatever();
     }
}
然后,控制器将获取工厂的一个实例,并让工厂决定实例化哪种类型。

用于工厂

您可以采取两种方法:

  • 工厂有两种方法,用于定位部件:
按照默认约定,如果您有一个注册名为“CustomFoo”的组件,则第二个方法将解析该组件,而第一个方法将获得默认组件

public interface IFooFactory
{
   IFoo GetFoo(...arguments);
   IFoo GetCustomFoo(..arguments);

   void ReleaseFoo(IFoo foo);
}
  • 在那里使用并封装选择逻辑
在Mike Hadlow的博客上遇到了一个问题,该问题使用在Windsor注册的代理返回许多命名类型注册中的一个

所以基本上温莎的注册可能是这样的

     container
            .Register(
                    Component.For<IReportFormatter>().ImplementedBy<ReportFormatterWord2003>().Named("word2003"),
                    Component.For<IReportFormatter>().ImplementedBy<ReportFormatterWord2007>().Named("word2007"),
                    Component.For<IReportFormatter>().ImplementedBy<ReportFormatterPdf>().Named("pdf"),
                    Component.For<Func<string, IReportFormatter>>().Instance(container.Resolve<IReportFormatter>),
                    Component.For<Foo>());

也许不像注册工厂那么容易理解,但却不需要工厂类。

为什么不传递一个参数作为“默认”参数来返回最初需要的类型?工厂方法是什么样子的?谢谢Jeff,我认为这里的问题是,我需要通过许多对象将参数向下传递到工厂被注入的点,以便它决定使用哪种类型。我希望避免这种情况。@Si-在不知道您案例的细节的情况下,似乎有必要改变设计,使(假设的)工厂更接近决定工厂产品的对象。至少,将参数保持在与工厂方法调用相同的调用链中应该会使代码更易于遵循和维护。这不是一个坏主意Jeff,然后我可以传递工厂创建的对象而不是参数。
Foo(Func<string, IReportFormatter> reportFormatterFactory)
container.Resolve<IReportFormatter>(string)
reportFormatterFactory("word2007");