c# - 如何使用 XmlSerializer 和 Autofac 注入(inject)依赖项?

标签 c# dependency-injection autofac xmlserializer

我有一个名为 SomeRule 的类,它可以以 XML 格式序列化。该类使用一个 ISomeService,我想通过 autofac 注入(inject)它。

[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 为我注入(inject)依赖项。

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 接口(interface)的已注册实现并将其分配给 SomeRule 实例的公共(public)属性。我正在寻找一个更好的解决方案,一个不需要类拥有公共(public)属性的解决方案。

有没有办法用 XmlSerializer 自动注入(inject)依赖?

最佳答案

从 DI 的角度来看,以数据为中心的对象的构造函数接受服务依赖性是相当有问题的,应该避免。

在练习 DI 时,我们尝试将应用程序组件的对象图组合(即包含行为并具有自己的依赖项的类)集中到应用程序中称为 Composition Root 的集中位置。 .

但是,包含构造函数依赖项的以数据为中心的对象会使这种做法复杂化,因为它要么强制从组合根中进行组合,要么强制添加用于创建这些对象的工厂抽象。

相反,您应该使用以下两种选择之一:

  1. 将数据和行为分开。这意味着将 SomeRuleDoSomething 方法移动到一个新类,该类将 SomeRule 作为其公共(public)方法中的参数。构造函数依赖项也将移至这个新类。
  2. 移除 SomeRule 的构造函数依赖项,而是使用方法注入(inject)将其注入(inject)到 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_service;

    // There's now just one constructor left
    public SomeRuleHandler(ISomeService service)
    { 
        m_service = service ?? throw new ArgumentNullException("service");
    }

    public void DoSomething(SomeRule rule)
    {
        m_service.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 service)
    {
        service.DoStuff(Attribute1);
    }
}

关于c# - 如何使用 XmlSerializer 和 Autofac 注入(inject)依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50930013/

相关文章:

c# - 在CompareValidator上添加JS验证

c# - 错误 : 40 - Could not open a connection to SQL Server

java - 依赖注入(inject)和观察者模式

c# - Autofac 解析单例对象中的非单例对象

c# - EF + AutoFac + async "The connection' s 当前状态正在连接”

c# - Azure 模拟器在启动 Web 角色后立即关闭。

typescript - 如何在 TypeScript 中为此依赖注入(inject)容器声明通用的映射类型

c# - 如何解决服务层内部的循环依赖

asp.net - .NET Core IoC RegisterAssemblyTypes等效项

c# - 使用 HAP 添加样式表