C# 使用动态构造函数注入的DI
我在使用具有构造函数属性的DI时遇到问题。我正在基于我的C# 使用动态构造函数注入的DI,c#,dependency-injection,constructor-injection,C#,Dependency Injection,Constructor Injection,我在使用具有构造函数属性的DI时遇到问题。我正在基于我的IPDFBuilder构建一个PDFBuilder public interface IPDFBuilder { string templatefilepath { get; } string templatefilename { get; } Dictionary<string, string> dict { get; } void CreatePDF(); } public clas
IPDFBuilder
构建一个PDFBuilder
public interface IPDFBuilder
{
string templatefilepath { get; }
string templatefilename { get; }
Dictionary<string, string> dict { get; }
void CreatePDF();
}
public class PDFBuilder : IPDFBuilder
{
public string templatefilename { get; private set; }
public string templatefilepath { get; private set; }
public Dictionary<string, string> dict { get; private set; }
public PDFBuilder(string templatefilename, string templatefilepath, Dictionary<string, string> dict)
{
this.templatefilename = templatefilename;
this.templatefilepath = templatefilepath;
this.dict = dict;
}
public void CreatePDF() {
//Do something
}
}
但是,我无法在startup类中设置PDFBuilder
的属性(DI注册已完成),因为不同的控制器将为PDFBuilder
类的属性使用不同的值。一个简单的解决方案是将属性的设置器公开,这样在操作方法中我可以设置值,然后调用CreatePDF()
。然而,这感觉不对。另一个简单的解决方案是删除类属性,将PDFBuilder
的3个属性作为方法属性传递给CreatePDF
方法,如下所示:
public void CreatePDF(string templatefilename, string templatefilepath, Dictionary<string, string> dict) {
//Do something
}
public interface IPDFConfiguration
{
string templatefilename {get;}
string templatefilepath {get;}
Dictionary<string, string> dict {get;}
}
public void CreatePDF(string templatefilename、string templatefilepath、Dictionary dict){
//做点什么
}
但是现在让我们假设我的PDFBuilder
有10个方法,它们都需要这3个属性。那么这不是正确的解决方案,对吗
那么正确的解决方案是什么呢?我在不同的类/接口实现中多次遇到这个问题,希望在这些情况下提供一些设计帮助。您正在将运行时数据注入到组件的构造函数中,这是一个很好的解决方案。解决方案是将这些运行时值从构造函数移到
CreatePDF
方法中:
public interface IPDFBuilder
{
void CreatePDF(string templatefilepath, string templatefilename,
Dictionary<string, string> dict);
}
公共接口IPDFBuilder
{
void CreatePDF(字符串templatefilepath、字符串templatefilename、,
词典(dict);
}
您可以将不同类型的PDFBuilder子类化(或原型化,取决于您的需求),并将它们注入相应的类中
我不知道您使用的是什么DI框架,但我非常确定有一个选项可以告诉框架您希望在特定类中注入什么样的依赖关系
编辑:请记住:此解决方案不适用于运行时已知的值。有两种方法可以完成您想要的操作:
1) Create factory for builder.
2) Create configurator for builder.
创建factory时,您基本上指定了对象的创建方式,因此可以为不同的构建器自由地将所需的一切设置到不同的实现中:
public inteface IPDFBuilderFactory
{
IPDFBuilder Create();
}
您需要传递所有依赖项-这是一个缺点。我个人不喜欢这种方法
另一种方法是创建如下配置:
public void CreatePDF(string templatefilename, string templatefilepath, Dictionary<string, string> dict) {
//Do something
}
public interface IPDFConfiguration
{
string templatefilename {get;}
string templatefilepath {get;}
Dictionary<string, string> dict {get;}
}
如果您打算在某个时候更改构建器,它将为您的构建器的初始化提供更大的灵活性。您还可以自由初始化此配置—常量、配置、数据库等
缺点之一——随着时间的推移,您的配置可能会变得非常笨拙,如果不进行重构,它将成为其他人的黑洞,因此请小心
选择最适合您的。这些是否是运行时数据还不清楚。这些可能是来自配置文件的配置数据。@YacoubMassad:问题的意思是“因为不同的控制器将使用不同的属性值”。这使我得出结论,这是运行时数据。但是你是对的,它仍然可能是配置数据,这将改变答案。很抱歉响应太晚,我定义了运行时数据!我将把这标记为一个答案,因为steven给我们的链接是一个很好的指导。这些参数/属性的值来自哪里?配置文件?还是来自用户?