简体   繁体   English

使用 a.Net Class 库进行依赖注入?

[英]Dependency injection with a .Net Class Library?

I have a Class library that does a lot of File IO.我有一个 Class 库,它做了很多文件 IO。 Its a bit difficult to test so I wanted to start using the System.IO.Abstractions package.它有点难以测试,所以我想开始使用System.IO.Abstractions package。 It has an interface that you can implement with either the real file system, or a mocked one.它有一个接口,您可以使用真实文件系统或模拟文件系统来实现该接口。

So when the code is running in production I want the real file system but when testing I want to mock it.因此,当代码在生产中运行时,我想要真正的文件系统,但在测试时我想模拟它。 My class doing IO stuff looks like this.我的 class 做 IO 的东西看起来像这样。

private readonly IFileSystem _fileSystem;

public Service(){
   _fileSystem = new FileSystem();  //In test we want Mock file system here
}

internal bool Run(){
   string[] sourceFilePaths = _fileSystem.Directory.GetFiles(_sourceDirectory, "*.xml", SearchOption.AllDirectories);
}

Now I want to use Dependency Injection in order to populate the _fileSystem instance in order to determine what to use.现在我想使用依赖注入来填充 _fileSystem 实例以确定使用什么。 The issue is that I do not know how to do this in a Class Library.问题是我不知道如何在 Class 库中执行此操作。 I have found tutorials but it seems that the consumer of the library have to do the injection.我找到了教程,但似乎图书馆的使用者必须进行注入。 My problem is that this class library is packaged and uploaded to a platform.我的问题是这个 class 库被打包上传到一个平台。 This platform cannot do anything with the package before using it.该平台在使用 package 之前无法对其进行任何操作。 So somehow the library has to figure out itself what instance to use.所以不知何故,图书馆必须自己弄清楚要使用什么实例。

One way I can think of is using the debug notation,我能想到的一种方法是使用调试符号,

#if DEBUG  #endif

But of course its messy and spreads the configuration around.但当然它的混乱和分散配置。

What is the proper way to use DI in a Class Library?在 Class 库中使用 DI 的正确方法是什么?

This is your problem:这是你的问题:

public Service(){
   _fileSystem = new FileSystem();  //In test we want Mock file system here
}

Your missing the injection part of dependency injection.您缺少依赖注入的注入部分。 This should look like this:这应该是这样的:

public Service(IFileSystem fileSystem){
   _fileSystem = fileSystem;  //In test we want Mock file system here
}

Why?为什么?

Now your class now longer a has a hard dependency on FileSystem , it now has a soft dependency on the interface for FileSystem , ( IFileSystem ).现在您的 class 现在不再对FileSystem具有硬依赖,它现在对FileSystem的接口具有软依赖( IFileSystem )。

Now when testing this class your can mock the interface:现在在测试这个 class 时,您可以模拟接口:

//example using nsubstitue (I prefer moq but I've been using this lately)
var mockIFileSystem = Substitute.For<IFileSystem>();
Service testInstance = new Service(mockIFileSystem);

In production code you now have two choices.在生产代码中,您现在有两个选择。 You could just inject all the dependencies yourself:您可以自己注入所有依赖项:

Service testInstance = new Service(new FileSystem);

this becomes clunky fast.这很快就会变得笨拙。 Or you could use a injection framework (I recommend SimpleInjector though this is just my opinion):或者你可以使用一个注入框架(我推荐SimpleInjector虽然这只是我的意见):

Dependency injection framework (with simple injector)依赖注入框架(带有简单的注入器)

With a DI framework you register all your dependencies and allow the framework to resolve them for you:使用 DI 框架,您可以注册所有依赖项并允许框架为您解析它们:

var container = new SimpleInjector.Container();

// Registrations here
container.Register<IFileSystem, FileSystem>();
container.Register<IService, Service>();

// Request instance
IService services = container.GetInstance<IService>();

Note: I never create an instance of IFileSystem above, the DI framework resolves it for me.注意:我从未在上面创建IFileSystem的实例,DI 框架为我解决了它。

for more information I'd suggest you have a look at similar questions, such as What is dependency injection?有关更多信息,我建议您查看类似的问题,例如什么是依赖注入?

Class libraries Class 库

There is nothing special about class libraries here. class 库在这里没有什么特别之处。 All you need to do is ensure that the dependency registration is called and that any consumer gets the initial dependency from your registration, or allow them to inject their own registration.您需要做的就是确保调用依赖注册,并且任何消费者都从您的注册中获取初始依赖,或者允许他们注入自己的注册。 There are multiple patterns to this and the correct solution depends on your goals.这有多种模式,正确的解决方案取决于您的目标。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM