寻找将温莎生活方式融入图书馆的方法

时间:2019-05-01 20:14:30

标签: c# asp.net-mvc inversion-of-control castle-windsor castle

我们有一个Web api项目,该项目引用了一个库,该库又在许多不同的系统之间共享。

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

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

public void SetupWindsor(){

    IWindsorContainer container = new WindsorContainer();

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

     SharedLibrary.RegisterDependancies(container);
}

共享库函数看起来像这样:

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.
}

我们现在希望Web api项目使用PerWebRequest生活方式,但其他系统可能希望使用不同的生活方式(此决定将取决于编写客户端应用程序的人-共享库将用于控制台和Windows应用程序-因此perwebrequest不适合他们使用)

我们想更改RegisterDependancies方法,以便我们能够过上这种生活方式。

PerWebRequest生活方式是否可以做到这一点?尽管过去做过类似的工作,但没有团结的问题,但我们中的一些人却一眼也不知道该怎么做。

我们正在寻找一种以上述方式解决问题的方法,或者是否有更好的方法来解决该问题也将有所帮助。

编辑以明确说明,共享库将接口IBar定义为公共接口,而将类Bar定义为内部接口,因此API无法进行注册-除非我不知道温莎有什么魔力。

2 个答案:

答案 0 :(得分:1)

您可以使用 LifeStyle.Is(LifestyleType)

在组件注册中设置生活方式

这样的事情可以让您传递生命周期。

public void RegisterDependencies(IWindsorContainer container, Castle.Core.LifestyleType lifestyleType)
{
    container.Register(Component.For<IBar>().ImplementedBy<Bar>().LifeStyle.Is(lifestyleType));
}

或者,按照惯例在程序集中进行注册,这将允许从API项目中控制生活方式,而无需公共实现  https://github.com/castleproject/Windsor/blob/master/docs/registering-components-by-conventions.md

答案 1 :(得分:0)

  

共享库将接口IBar定义为公共接口,但将Bar类定义为内部接口,因此API无法注册

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

IWindsorContainer container = new WindsorContainer();
SharedLibrary.RegisterDependancies(container);
IBar bar = container.Resolve<IBar>();

保留Barinternal可能有多种原因,但是由于您已经可以运行上述代码,所以为什么不简单地让共享库公开工厂呢?

IBar bar = SharedLibrary.CreateBar();

那会简单得多,并将共享库与容器解耦。通常,这是我可以提供的有关依赖关系注入和可重用库的最佳建议:使用依赖关系注入模式,而不是容器。有关更多详细信息,请参见我的文章DI-Friendly Library

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

内部课程

出于某些合理的原因,我们希望保留一些类internal,但是我经常看到没有明显原因的代码库,其中的类是internal。我使用数十年C#代码的经验是,无缘无故地使用internal类的情况远胜于有充分理由的情况。

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

在OP中,很明显IBarBar实现。这个可以是将问题简化为基本要素的人为因素(这样做很好,顺便说一句),但我的印象是Bar是唯一的 类,实现IBar。是这样吗?

如果是,则Bar类必须公开IBar定义的方法。因此,该类的API已经公开,那么为什么要隐藏该类呢?那么,唯一隐藏的是构造函数...

完美的风暴

有时候,当我提供上述建议时,我遇到的答复不是问题所在。问题在于如何改变温莎城堡的生活方式(顺便说一下,you can)。

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

  • 该库应该在多个上下文(网络,控制台,桌面等)中可用
  • 图书馆取决于温莎城堡
  • 接口是公共的,但实现类不是

这使事情变得复杂-因此出现了堆栈溢出的问题。

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

如果您将大多数库类公开,则使用该库将更加容易。