我有一个名为sqlplus_delete_table = 'echo "TRUNCATE TABLE ' + db_user + '.' + table + ' DROP STORAGE;"'
sqlplus_connection = db_user + '/' + db_password + '@' + db_name
os.system(sqlplus_delete_table + ' | sqlplus -s ' + sqlplus_connection)
的类,可以以XML格式进行序列化。该类使用一个SomeRule
,我想通过autofac注入它。
ISomeService
现在,我的程序接收到一个我想反序列化的XML字符串,但同时我也可以通过autofac为我注入依赖项。
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
private readonly ISomeService m_someService;
private SomeRule()
{
}
public SomeRule(ISomeService someService)
{
m_someService = someService;
}
public void DoSomething()
{
m_someService.DoStuff(Attribute1);
}
}
public interface ISomeService {
void DoStuff(string param);
}
public class SomeServiceImpl : ISomeService
{
public void DoStuff(string param)
{
// Do something with the stuff.
}
}
我可以通过调用autofac容器来完成这项工作,获取void Main()
{
string serializedRule = "<?xml version=\"1.0\" encoding=\"utf-16\"?><SomeRule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" Attribute1=\"Huuuuuge\" Attribute2=\"Cofveve\" />";
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SomeRule));
var stringBuilder = new StringBuilder(serializedRule);
var newRule = xmlSerializer.Deserialize(new StringReader(stringBuilder.ToString())) as SomeRule;
// ISomeService was not injected yet. Is it possible?
}
接口的注册实现,并将其分配给ISomeService
实例的公共属性。我正在寻找一种更好的解决方案,该解决方案不需要班级拥有公共财产。
是否可以使用SomeRule
自动插入依赖项?
答案 0 :(得分:4)
从DI的角度来看,让带有以数据为中心的对象带有接受服务依赖关系的构造函数是很成问题的,应该避免。
在实践DI时,我们尝试将应用程序组件的对象图的构成(即,包含行为并具有自身依赖关系的类)集中到应用程序中称为Composition Root的集中位置。 / p>
但是,包含构造函数依赖项的以数据为中心的对象使这种做法变得复杂,因为它要么将合成强制从“合成根”中排除,要么强制添加用于创建这些对象的工厂抽象。
相反,您应该使用以下两种选择之一:
SomeRule
的{{1}}方法移动到新类,该类将DoSomething
作为其公共方法中的参数。构造函数的依赖关系也将移至该新类。SomeRule
的构造函数依赖项,而是使用方法注入将其注入SomeRule
中。选项1可能看起来像这样:
DoSomething
使用选项2,结果如下:
// SomeRule only contains data. Much simpler
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
}
// Moved behavior to new class. This class can be injected
// into consumers, as usual.
public class SomeRuleHandler : IRuleHandler<SomeRule>
{
private readonly ISomeService m_someService;
// There's now just one constructor left
public SomeRuleHandler(ISomeService someService)
{
m_someService = someService ?? throw new ArgumentNullException("someService");
}
public void DoSomething(SomeRule rule)
{
m_someService.DoStuff(rule.Attribute1);
}
}