如何使用 XmlSerializer 和 autofac 注入依赖项?
How to inject dependencies with XmlSerializer and autofac?
我有一个名为 SomeRule
的 class,可以以 XML 格式序列化。 class 使用我想通过 autofac 注入的 ISomeService
。
[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.
}
}
现在,我的程序接收到一个 XML 字符串,我想将其反序列化,同时让 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?
}
我可以通过调用 autofac 容器来完成这项工作,获取 ISomeService
接口的注册实现并将其分配给 SomeRule
的 public 属性实例。我正在寻找一个更好的解决方案,一个不需要 class 有 public 属性.
的解决方案
有没有办法用XmlSerializer
自动注入依赖?
从 DI 的角度来看,以数据为中心的对象的构造函数接受服务依赖性是相当有问题的,应该避免。
在练习 DI 时,我们尝试将应用程序组件的对象图组合(即包含行为并具有自己的依赖项的 classes)集中到应用程序中称为Composition Root.
但是,包含构造函数依赖项的以数据为中心的对象使这种做法变得复杂,因为它要么强制从组合根中进行组合,要么强制添加用于创建这些对象的工厂抽象。
相反,您应该使用以下两种选择之一:
- 分离数据和行为。这意味着将
SomeRule
的 DoSomething
方法移动到新的 class,它将 SomeRule
作为其 public 方法中的参数。构造函数依赖项也将移动到这个新的 class。
- 删除
SomeRule
的构造函数依赖项,而是使用方法注入将其注入 DoSomething
。
选项 1 可能如下所示:
// 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);
}
}
使用选项 2,结果如下:
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
// No more constructors. The dependency is supplied in the method,
// but *not* stored.
public void DoSomething(ISomeService someService)
{
someService.DoStuff(Attribute1);
}
}
我有一个名为 SomeRule
的 class,可以以 XML 格式序列化。 class 使用我想通过 autofac 注入的 ISomeService
。
[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.
}
}
现在,我的程序接收到一个 XML 字符串,我想将其反序列化,同时让 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?
}
我可以通过调用 autofac 容器来完成这项工作,获取 ISomeService
接口的注册实现并将其分配给 SomeRule
的 public 属性实例。我正在寻找一个更好的解决方案,一个不需要 class 有 public 属性.
有没有办法用XmlSerializer
自动注入依赖?
从 DI 的角度来看,以数据为中心的对象的构造函数接受服务依赖性是相当有问题的,应该避免。
在练习 DI 时,我们尝试将应用程序组件的对象图组合(即包含行为并具有自己的依赖项的 classes)集中到应用程序中称为Composition Root.
但是,包含构造函数依赖项的以数据为中心的对象使这种做法变得复杂,因为它要么强制从组合根中进行组合,要么强制添加用于创建这些对象的工厂抽象。
相反,您应该使用以下两种选择之一:
- 分离数据和行为。这意味着将
SomeRule
的DoSomething
方法移动到新的 class,它将SomeRule
作为其 public 方法中的参数。构造函数依赖项也将移动到这个新的 class。 - 删除
SomeRule
的构造函数依赖项,而是使用方法注入将其注入DoSomething
。
选项 1 可能如下所示:
// 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);
}
}
使用选项 2,结果如下:
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
// No more constructors. The dependency is supplied in the method,
// but *not* stored.
public void DoSomething(ISomeService someService)
{
someService.DoStuff(Attribute1);
}
}