简体   繁体   English

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

[英]How can I pass a runtime parameter to a previously registered factory method using castle windsor?

I have a reporting MVC application that uses Castle Windsor. 我有一个使用Castle Windsor的报告MVC应用程序。

On application start up (in global.asax) all of the types are registered and then each subsequent request to the application resolves the relevant report type and windsor automatically handles the dependencies. 在应用程序启动时(在global.asax中),所有类型都被注册,然后对应用程序的每个后续请求都会解析相关的报告类型,windsor会自动处理依赖项。

I need to switch one of the dependant types for another depending on a parameter passed in on the request. 我需要根据请求中传入的参数切换其中一种依赖类型。

How can I achieve this? 我怎样才能做到这一点?

I have registered a factory method with windsor to handle the resolution of the switchable types but as this is registered on application start how can I pass a parameter to the factory method when the parameter is only available on a later request? 我已经使用windsor注册了一个工厂方法来处理可切换类型的分辨率但是由于这是在应用程序启动时注册的,当参数仅在以后的请求中可用时,如何将参数传递给工厂方法?

If I try registering the factory for each request it works on the first request but then complains on all subsequent requests that the factory is already registered. 如果我尝试为每个请求注册工厂,它​​会在第一次请求时工作,但随后会抱怨工厂已经注册的所有后续请求。 Unregistering the factory after each request doesnt sound like the right thing to be doing. 在每次请求之后取消注册工厂听起来不是正确的事情。

When you need to resolve types at runtime, the normal solution is to inject a factory that can make the decision at the appropriate time: 当您需要在运行时解析类型时,通常的解决方案是注入一个可以在适当的时间做出决策的工厂:

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

Classes that previously required an IReport should demand an IReportFactory instead. 以前需要IReport应该要求IReportFactory

You definitely don't want to go modifying your container on a per-request basis. 您绝对不希望根据请求修改容器。 That's a recipe for disaster. 这是灾难的秘诀。

You've got two options. 你有两个选择。 The first is to use HttpContext.Current inside the factory method. 第一种是在工厂方法中使用HttpContext.Current。

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

     return DefaultWhatever();
}

The other (better) option would be to inject a factory type that resolves the correct implementation, rather than having the container do it for you. 另一个(更好的)选择是注入一个解析正确实现的工厂类型,而不是让容器为你做。

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

         return new DefaultWhatever();
     }
}

Your controller would then take an instance of the factory, and would let the factory make the decision of which type to instantiate. 然后,您的控制器将获取工厂的实例,并让工厂决定实例化哪种类型。

Use TypedFactoryFacility for your factory. 为您的工厂使用TypedFactoryFacility

You can take two appraoches: 你可以拿两个appraoches:

With default convention, if you have a component registered with name "CustomFoo" the 2nd method would resolve that component, whereas the first one would get the default one. 使用默认约定,如果您有一个名为“CustomFoo”的组件,则第二个方法将解析该组件,而第一个方法将获得默认组件。

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

   void ReleaseFoo(IFoo foo);
}

Have come across an article on Mike Hadlow's blog that uses a delegate registered with Windsor to return one of a number of named type registrations... 在Mike Hadlow的博客上发现了一篇文章 ,该文章使用在Windsor注册的代表返回一些已命名的类型注册...

So basically the Windsor registration might look something like this... 所以基本上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>());

and the Foo constructor would take a parameter of the delegate type 并且Foo构造函数将获取委托类型的参数

Foo(Func<string, IReportFormatter> reportFormatterFactory)

now when Windsor resolves Foo, reportFormatterFactory is not resolved to an implementation of IReportFormatter instead it simply holds a reference to the container.Resolve method... 现在当Windsor解析Foo时,reportFormatterFactory没有解析为IReportFormatter的实现,而只是它持有对container.Resolve方法的引用...

container.Resolve<IReportFormatter>(string)

that can later be used to get the correct IReportFormatter by calling... 以后可以通过调用来获取正确的IReportFormatter ...

reportFormatterFactory("word2007");

Perhaps not as easy to understand as registering a factory but does away with the need for the factory class. 也许并不像注册工厂那样容易理解,但却不需要工厂级。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在温莎城堡中,我该如何覆盖在FromThisAssembly()中注册的类型 - In Castle Windsor how can I override a type registered with FromThisAssembly() 如何将依赖性传递给城堡温莎型工厂 - How to Pass a Dependency to a Castle Windsor Typed Factory 温莎城堡:类型工厂未使用注册的子解析器 - Castle Windsor: Typed Factory not using registered sub resolver 温莎城堡:类型化工厂设施能否将参数传递给类型的依赖项之一? - Castle Windsor: Can a Typed Factory Facility pass a parameter down to one of the type's dependencies? 如何在温莎城堡的解决方案管道中传递参数? - How can I pass an argument down the resolution pipeline in Castle Windsor? 在Castle.Windsor工厂方法中使用Moq - Using Moq in Castle.Windsor factory method throws 如何使用Castle Windsor注册通用装饰器? - How can I register a generic decorator using Castle Windsor? Castle Windsor:当我的装配无法访问基础类型时,如何注册工厂方法? - Castle Windsor: How do I register a factory method, when the underlying type isn't accessible to my assembly? 如何命名温莎城堡中的容器? - How can I name a container in Castle Windsor? 如何使用Castle Windsor的基本接口注册服务工厂模式 - How to register Service Factory Pattern using base interface with Castle Windsor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM