gpt4 book ai didi

c# - Ninject Constructor 参数检查参数是否存在

转载 作者:行者123 更新时间:2023-11-30 14:22:38 25 4
gpt4 key购买 nike

我想知道无论如何,如何使用 Ninject 进行参数存在性检查?

我指的是:让我们有一个理论类和一个接口(interface):

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);
}
}

然后在代码的某处,我将通过内核获取 IFIleExistenceCheck 接口(interface)的实例,如下所示:

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

这会工作得很好,问题是,只要文件路径参数的名称保持不变,它就会工作。假设有一天有人会决定,filePath 是不必要的,并将其重命名为 path。代码本身仍会编译,但它不会导致任何错误,直到有人真正调用 Bar() 方法。

有什么办法可以防止这种情况发生吗?

我真的不想公开 filePath。我仍然希望它作为构造函数的参数传递。我不想更改 FileCheck() 的签名以接受 filePath 作为参数,我什至不想将 filePath 更改为可公开访问字段。

最佳答案

这是滥用 DI 容器作为 service locator还有另一个原因为什么它的服务定位器被认为是 anti-pattern .

如果您使用依赖注入(inject)模式,您设计的示例就不会发生。重构您的示例以使用依赖项注入(inject),它看起来像这样:

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);
}
}

Foo 类

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

composition root , 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();
}
}

如果需要检查 filePath 参数是否存在,可以使用保护子句来完成此检查。您只需要使用 dependency injection pattern ,并通过方法参数传递运行时数据(文件路径)。

如果您希望 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();
}
}

关于c# - Ninject Constructor 参数检查参数是否存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48679014/

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