繁体   English   中英

在构造函数中使用运行时参数进行依赖注入

[英]Dependency injection with runtime parameters in the constructor

我开始实现一个控制台应用程序并学习 DI 和 IOC。

所以我决定写两个 class

public class Reporter {
        public readonly IDataExport exporter;
        public readonly IService service;
    
        Reporter(IService service, IDataExport export ) {
        service = service;
        exporter = exporter;
    } 

    public void Run() {
       var data = service.GetData();
       exporter.Export(data);
    } 

}

出口商定义为

  public class CsvExporter : IDataExport {
        public readonly StreamWriter writter;
        
          CsvExporter(StreamWriter writer) {
        writer = writer;
        } 
    
     
     //interface implementation
     public async Task Export(IEnumerable<Person> data) 
    {
       var formmatedData = FormartData(data) 
       await writer.WriteAsync(formattedData);
       await writer.FlushAsync();
    } 
 }
    

我的问题是,如果我必须使用需要编写 csv 并且文件名必须在运行时作为参数传递的 StreamWriter,我该如何处理 IOC

亲切的问候和感谢

解决这个问题的典型方法是使用工厂。 有很多方法可以构建它,这只是一个例子:

public interface IDataExportFactory{
     IDataExport Create(Stream stream);
}

另一种选择是将参数移动到方法

public async Task Export(IEnumerable<Person> data, Stream stream)

对于这个相当简单的示例,两种选择都非常相似。 如果您有一个可以导出不同类型数据或做更多事情的大型界面,前者可能会更好。

我建议使用Stream而不是StreamWriter ,因为前者更通用。

如果您需要导出器忽略导出目标,您可以注入一个已经具有 stream 的 CsvWriter 实例,或者有一些获取 stream 的方法。 但从问题中不清楚究竟应该由哪个组件负责创建 stream,或者是否所有出口商都应该能够写入 stream。

If you are using a an IoC container that supports method injection like autoface ( docs ) you can use it to inject the Stream outside of the class scope, and then let some other class to be responsible for initiating the Stream object:

var builder = new ContainerBuilder();
builder.RegisterType<WriterService>().As<IWriterService>();
builder.RegisterType<CsvExporter>()
    .OnActivated(IActivatedEventArgs<CsvExporter> e) =>
    {
        var stream = e.Context.Resolve<IWriterService>(); --> runtime resolving!!
        e.Instance.SetStream(stream);
    });    

并修改您的 class 以具有SetStream方法:

public class CsvExporter : IDataExport {
    private Stream _writter;
    
    SetStream(Stream writer) {
        this._writer = writer;
    }
 
    //interface implementation
    public async Task Export(IEnumerable<Person> data) 
    {
        var formmatedData = FormartData(data) 
        await this._writer.WriteAsync(formattedData);
        await this._writer.FlushAsync();
    } 
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM