gpt4 book ai didi

c# - 难以通过工厂 DI 理解 ninject(或一般的 IOC 容器)?

转载 作者:太空狗 更新时间:2023-10-29 21:18:58 25 4
gpt4 key购买 nike

好的,最近我一直在阅读 ninject,但我无法理解是什么让它比维基页面上的“穷人”DI 更好。可悲的是我浏览了他们在 wiki 上的所有页面,但仍然不明白 =(。

通常我会将我的服务类包装在工厂模式中,这样处理 DI:

public static class SomeTypeServiceFactory
{
public static SomeTypeService GetService()
{
SomeTypeRepository someTypeRepository = new SomeTypeRepository();
return = new SomeTypeService(someTypeRepository);

}

}

在我看来,这很像模块:

public class WarriorModule : NinjectModule {
public override void Load() {
Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf().InSingletonScope();
}
}

每个类都有它的关联模块,你将它的构造函数绑定(bind)到一个具体的实现。虽然 ninject 代码少了 1 行,但我只是没有看到优势,无论何时添加/删除构造函数或更改接口(interface)构造函数的实现,您都必须以与在工厂中几乎相同的方式更改模块不?所以看不到这里的优势。

然后我想我可以像这样想出一个通用的基于约定的工厂:

 public static TServiceClass GetService<TServiceClass>()
where TServiceClass : class
{
TServiceClass serviceClass = null;

string repositoryName = typeof(TServiceClass).ToString().Replace("Service", "Repository");
Type repositoryType = Type.GetType(repositoryName);

if (repositoryType != null)
{
object repository = Activator.CreateInstance(repositoryType);
serviceClass = (TServiceClass)Activator.CreateInstance(typeof (TServiceClass), new[]{repository});
}

return serviceClass;
}

但是,这很糟糕,原因有两个:1) 它严格依赖于命名约定,2) 它假设存储库永远不会有任何构造函数(不正确)并且服务的唯一构造函数将是它对应的存储库(也不是真的)。我被告知“嘿,这是你应该使用 IoC 容器的地方,在这里会很棒!” 因此我的研究开始了......但我只是没有看到它并且很难理解它...

ninject 是否有某种方法可以在没有特定声明的情况下自动解析类的构造函数,以便在我的通用工厂中使用它会很好(我也意识到我可以使用反射手动执行此操作,但这是一个性能损失和 ninject在他们的页面上说他们不使用反射)。

非常感谢对这个问题的启发和/或展示如何在我的通用工厂中使用它!

编辑:回答

因此,由于下面的解释,我能够完全理解 ninject 的强大之处,我的通用工厂如下所示:

public static class EntityServiceFactory
{
public static TServiceClass GetService<TServiceClass>()
where TServiceClass : class
{
IKernel kernel = new StandardKernel();

return kernel.Get<TServiceClass>();
}
}

非常棒。一切都是自动处理的,因为具体类具有隐式绑定(bind)。

最佳答案

IoC 容器的好处随着项目的规模而增长。对于小型项目,与像您的工厂这样的“穷人的 DI”相比,它们的 yield 微乎其微。想象一个有数千个类的大型项目,并且在许多类中使用了一些服务。在这种情况下,您只需说一次这些服务是如何解决的。在工厂里,你必须为每个类(class)一次又一次地做这件事。

示例:如果您有一个服务 MyService : IMyService 和一个需要 IMyService 的类 A,您必须告诉 Ninject 它将如何解析这些类型就像在您的工厂中一样。这里的好处是微乎其微的。但是,一旦您的项目增长并添加了一个类 B,它也依赖于 IMyService,您只需告诉 Ninject 如何解析 B。 Ninject 已经知道如何获取 IMyService。另一方面,在工厂中,您必须再次定义 B 如何获取其 IMyService

更进一步。在大多数情况下,您不应该一一定义绑定(bind)。而是使用基于约定的配置 (Ninject.Extension.Conventions)。有了它,您可以将类(服务、存储库、 Controller 、演示器、 View ......)分组在一起,并以相同的方式配置它们。例如。告诉 Ninject 所有以 Service 结尾的类都应该是单例并发布它们的所有接口(interface)。这样一来,您只有一个配置,添加另一项服务时无需更改。

此外,IoC 容器不仅仅是工厂。还有更多。例如。生命周期管理,拦截,....

kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses()
.InNamespace("Services")
.BindToAllInterfaces()
.Configure(b => b.InSingletonScope()));
kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses()
.InNamespace("Repositories")
.BindToAllInterfaces());

关于c# - 难以通过工厂 DI 理解 ninject(或一般的 IOC 容器)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9021639/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com