Kaj*_*ama 3 .net c# dependency-injection ninject inversion-of-control
我想知道无论如何,如何使用Ninject进行参数存在检查?
我指的是:让我们有一个理论类和一个接口:
public interface IFileExistenceCheck
{
bool FileExist();
}
public class FileExistenceChecker : IFileExistenceCheck
{
private readonly string filePath;
private readonly IFileSystem fileSystem;
public FileExistenceChecker(IFileSystem fileSystem, string filePath)
{
this.fileSystem = fileSystem;
this.filePath = filePath;
}
public bool FileExist()
{
return this.fileSystem.File.Exists(this.filePath);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在代码中的某个地方,我将IFIleExistenceCheck通过内核获得一个接口实例,如下所示:
public class Foo()
{
public void Bar()
{
// do something
var filePath = SomeMagicString;
var filePathArgument = new ConstructorArgument("filePath", filePath); // <- This part I do not really like
var checker = Kernel.Get<IFileExistenceCheck>(filePathArgument);
var fileExist = checker.FileExist();
// do the rest of code
}
}
Run Code Online (Sandbox Code Playgroud)
这将工作得很好,问题是,只有文件路径参数的名称保持不变,它才会起作用.让我们说有一天会有人决定,这filePath是不必要的,只是重命名path.代码本身仍然会编译,但是在有人实际调用该Bar()方法之前不会导致任何错误.
有什么方法可以防止这种情况发生吗?
我真的不想曝光filePath.我仍然希望它作为构造函数的参数传递.我不想更改签名作为参数FileCheck()接受filePath,我甚至不想更改filePath为可公开访问的字段.
这是滥用DI容器作为服务定位器,而服务定位器的另一个原因被认为是反模式.
如果您使用依赖注入模式,那么您的设计示例将不会发生.重构您的示例以使用依赖注入,它看起来像这样:
public interface IFileExistanceCheck
{
bool FileExist(string filePath);
}
public class FileExistanceChecker : IFileExistanceCheck
{
private readonly IFileSystem fileSystem;
public FileExistanceChecker(IFileSystem fileSystem)
{
if (fileSystem == null)
throw new ArgumentNullException(nameof(fileSystem));
this.fileSystem = fileSystem;
}
// Pass runtime data through the method parameters!
public bool FileExist(string filePath)
{
// Prevent an empty file path from being used
if (string.IsNullOrEmpty(filePath))
throw new ArgumentNullException(nameof(filePath));
return this.fileSystem.File.Exists(filePath);
}
}
Run Code Online (Sandbox Code Playgroud)
public class Foo
{
private readonly IFileExistanceCheck fileExistanceCheck;
public Foo(IFileExistanceCheck fileExistanceCheck)
{
if (fileExistanceCheck == null)
throw new ArgumentNullException(nameof(fileExistanceCheck));
this.fileExistanceCheck = fileExistanceCheck;
}
public void Bar()
{
// do something
var filePath = SomeMagicString;
var fileExist = fileExistanceCheck.FileExist(filePath);
// do the rest of code
}
}
Run Code Online (Sandbox Code Playgroud)
在组合根目录下,Ninject将它们组合在一起并开始Foo运行.
class Program
{
static void Main(string[] args)
{
// Begin composition root
var kernel = new StandardKernel();
kernel.Bind<IFileSystem>().To<FileSystem>();
kernel.Bind<IFileExistanceCheck>().To<FileExistanceChecker>();
var app = kernel.Get<Foo>();
// End composition root
app.Bar();
}
}
Run Code Online (Sandbox Code Playgroud)
如果需要检查filePath参数是否存在,可以使用guard子句进行此检查.您只需要使用依赖项注入模式,并通过方法参数传递运行时数据(文件路径).
如果您希望filePath它是在应用程序启动时通过构造函数传递的配置值,那么使用检查文件存在的服务似乎毫无意义.在这种情况下,您应该在允许应用程序运行之前检查文件是否存在.
class Program
{
static void Main(string[] args)
{
var filePath = "SomeFileThatShouldExist.txt";
// Check configuration
if (!File.Exists(filePath))
throw new InvalidOperationException("Invalid configuration");
// Begin composition root
var kernel = new StandardKernel();
kernel.Bind<Foo>().To(new Bar(filePath));
// Register other services...
var app = kernel.Get<Foo>();
// End composition root
app.Bar();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
82 次 |
| 最近记录: |