Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/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# 寻找将温莎生活方式传递到图书馆的方法_C#_Asp.net Mvc_Inversion Of Control_Castle Windsor_Castle - Fatal编程技术网

C# 寻找将温莎生活方式传递到图书馆的方法

C# 寻找将温莎生活方式传递到图书馆的方法,c#,asp.net-mvc,inversion-of-control,castle-windsor,castle,C#,Asp.net Mvc,Inversion Of Control,Castle Windsor,Castle,我们有一个web api项目,它引用了一个库,而这个库又在许多不同的系统之间共享 该库公开了一个“registerDependances(IWindsorContainer)”函数,调用该函数时将注册该特定库的所有依赖项 因此,当web api应用程序启动时,它会进行自己的注册,然后调用共享库,类似于以下伪代码: public void SetupWindsor(){ IWindsorContainer container = new WindsorContainer();

我们有一个web api项目,它引用了一个库,而这个库又在许多不同的系统之间共享

该库公开了一个“registerDependances(IWindsorContainer)”函数,调用该函数时将注册该特定库的所有依赖项

因此,当web api应用程序启动时,它会进行自己的注册,然后调用共享库,类似于以下伪代码:

public void SetupWindsor(){

    IWindsorContainer container = new WindsorContainer();

    container.Register(Component.For<iFoo>().ImplementedBy<Foo>());

     SharedLibrary.RegisterDependancies(container);
}
public void SetupWindsor(){
IWindsorContainer=新WindsorContainer();
container.Register(Component.For().ImplementedBy());
共享图书馆。注册设备(容器);
}
共享库函数看起来有点像这样:

public void RegisterDependancies(IWindsorContainer container)
{
    container.Register(Component.For<iBar>().ImplementedBy<Bar>());
    //In this instance Bar is internal so could not be registered by the api project.
}
public void registerdependances(IWindsorContainer)
{
container.Register(Component.For().ImplementedBy());
//在此实例中,Bar是内部的,因此无法由api项目注册。
}
我们现在希望web api项目使用PerWebRequest生活方式,但其他系统可能希望使用不同的生活方式(此决定将取决于编写客户端应用程序的人-共享库将用于控制台和windows应用程序-因此PerWebRequest不适合他们使用)

我们想改变RegisterDependances方法,这样我们就可以在生活方式中传递信息

PerWebRequest的生活方式有可能做到这一点吗?我们中的一些人看了一眼,却不知道该怎么做——尽管我们过去也做过类似的事情,但没有遇到团结的问题

我们正在寻找一种方法来解决所描述的问题,或者如果有更好的方法来解决这个问题,这也会很有帮助


编辑以澄清,共享库将接口IBar定义为public,但将类栏定义为internal,因此API无法进行注册-除非我不知道温莎有什么神奇之处。

您可以使用
生活方式.is(lifestyle Type)
在组件注册上设置生活方式

类似这样的东西将允许您传递生命周期

public void RegisterDependencies(IWindsorContainer container, Castle.Core.LifestyleType lifestyleType)
{
    container.Register(Component.For<IBar>().ImplementedBy<Bar>().LifeStyle.Is(lifestyleType));
}
public void RegisterDependencies(IWindsorContainer容器,Castle.Core.LifestyleType LifestyleType)
{
container.Register(Component.For().ImplementedBy().LifeStyle.Is(lifestyleType));
}
或者,看看按照惯例向大会注册,这将允许在API项目中控制生活方式,而无需公开实现

共享库将接口IBar定义为public,而将类栏定义为internal,因此API无法进行注册

让我们检查一下这个设计决策。虽然没有外部调用者可以创建
Bar
对象,但他们可以创建
IBar
对象:

IWindsorContainer container = new WindsorContainer();
SharedLibrary.RegisterDependancies(container);
IBar bar = container.Resolve<IBar>();
这将更加简单,并将共享库与容器解耦。一般来说,这是关于依赖项注入和可重用库的最好建议:使用依赖项注入模式,而不是容器。有关更多详细信息,请参阅我的文章

如果您仍然希望在宿主项目(例如Wep API项目)中使用DI容器,则可以针对该静态工厂方法注册
IBar

内部类 人们希望保留一些类
internal
,这是有正当理由的,但我经常看到代码库中的类是
internal
,没有明显的原因。我对几十年的C#代码的经验是,类是
内部的
,没有好的理由的情况远远超过了有好的理由的情况

Bar
真的必须是内部的吗?为什么?

从OP可以清楚地看出,
IBar
是通过
Bar
实现的。这可能是将问题简化为基本问题的人工制品(顺便说一句,做得很好),但我得到的印象是,
Bar
是唯一实现
IBar
的类。是这样吗

如果是这样,
Bar
类必须公开由
IBar
定义的方法。因此,该类的API已经是公共的,那么为什么要隐藏该类呢?那么,唯一隐藏的就是构造器

完美风暴 有时,当我给出上述建议时,我会得到一个与问题无关的回答。问题是如何改变温莎城堡的生活方式(顺便说一句,这是什么)

另一方面,这个问题几乎是完美的(小)风暴,它说明了为什么可重用库不应该依赖于DI容器:

  • 库应该在多个上下文(web、控制台、桌面等)中可用
  • 这个图书馆依靠温莎城堡
  • 接口是公共的,但实现类不是
这使事情变得复杂-因此这里的问题是堆栈溢出

我最好的建议是保持简单。消除对Castle Windsor的依赖将使库的开发和重用更容易,而不是更难


如果将大多数库类公开,那么使用库就更容易了。

根据Mark Seeman的《依赖注入》一书,库不应该有组合根。因此,他们不关心编写应用程序。你不仅在生活方式上有问题,在交换实现上也有问题。只需将完整注册留给你的应用程序,你不知道这将如何工作。根据问题库有公共接口,这些接口有内部实现,因此应用程序无法访问类进行注册,编辑问题以澄清这一点。不太同意Mark Seeman的方法,原因正是@5NRF提到的。作为一般原则,我将以组件行为支持任何部署场景的方式构建库安装程序。“按请求”的生活方式应该限制在尽可能少的组成点上——最好是在图书馆之外。然后你就可以重新开始了
IBar bar = SharedLibrary.CreateBar();