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

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

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

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

因此,当 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 生活方式来做到这一点?我们中的一些人看了看,但不知道如何去做——尽管过去曾做过类似的事情,没有出现任何团结问题。

我们要么正在寻找一种方法来以所描述的方式解决问题,要么是否有更好的方法来解决这个问题,这也会有所帮助。

编辑澄清一下,共享库将接口(interface) ​​IBar 定义为公共(public)接口(interface),但将类 Bar 定义为内部接口(interface),因此 API 无法进行注册 - 除非温莎中有一些我不知道的魔法。

最佳答案

the shared library defines the interface IBar as public but the class Bar as internal so the API cannot do the registration

让我们暂时检查一下该设计决策。虽然外部调用者无法创建 Bar 对象,但他们可以创建 IBar 对象:

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

Bar 类保留在 internal 中可能有多种原因,但既然您已经可以运行上面这样的代码,为什么不简单地让共享库公开一个工厂?

IBar bar = SharedLibrary.CreateBar();

这会更简单,并将共享库与容器分离。一般来说,这是我可以给出的关于依赖注入(inject)和可重用库的最佳建议:使用依赖注入(inject)模式,而不是容器。看我的文章DI-Friendly Library了解更多详情。

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

内部类

人们想要保留某些类内部是有正当理由的,但我经常看到代码库中的类是内部,没有明显的原因。我对数十年 C# 代码的经验是,没有充分理由将类设为内部的情况远远多于有充分理由的情况。

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

从OP中可以清楚地看出,IBar是由Bar实现的。这可能是将问题简化为本质的人为因素(顺便说一句,做得很好),但我的印象是 Bar唯一> 实现IBar 的类。是这样吗?

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

完美 Storm

有时,当我提出上述建议时,我得到的回应并不是问题的本质。问题是如何改变温莎城堡的生活方式(顺便说一句,you can)。

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

  • 该库应可在多个环境中使用(网络、控制台、桌面等)
  • 该库依赖于温莎城堡
  • 接口(interface)是公共(public)的,但实现类不是公共(public)的

这让事情变得复杂 - 因此 Stack Overflow 上出现了这个问题。

我最好的建议是让事情变得简单。消除对 CaSTLe Windsor 的依赖将使库的开发和重用变得更容易,而不是更困难。

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

关于c# - 寻找将温莎生活方式融入图书馆的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55942172/

相关文章:

c# - C++ 或 C# : Reading commands from a Human Interface Device(HID)

c# - 中继器 databinder.eval 双引号

c# - 使用 C# Web.config 文件连接到 Access 数据库

C# - 在事件目录中查找用户管理器

asp.net - 如何在 ASP.NET MVC 中实现 Disqus?

asp.net-mvc - 在 Web api 和类库中使用 unity DI

c# - 带有解析数据的 ASP.NET MVC 4

dependency-injection - Mono 兼容的依赖注入(inject)框架

spring - 使用包私有(private)类的 Grails 依赖注入(inject)

entity-framework - 每次使用都需要创建/处理的项目的依赖注入(inject)