如何将抽象方法重构为DI

时间:2017-10-16 12:05:33

标签: c# dependency-injection refactoring abstract-methods

我有Asp.net Core项目,默认DI实现。 所以我通过DI获得了BL-services实例,存储库,EF-context。 我有抽象方法,通过参数返回某些类型。

IDocumentPreprocessor CreateDocumentPreprocessor(DocType docType)
    {
        switch (docType)
        {
            case DocType.Txt:
                return new TxtPreprocessor(_context, _docRepository);
            case DocType.Doc:
                return new DocPreprocessor(_docRepository);

            default:
                throw new ...
        }
    }

我不喜欢在这里通过" new"直接创建实例。 但我不确定是否可以将此逻辑传递给DI。 那么问题 - 如何将其重构为DI使用?

2 个答案:

答案 0 :(得分:3)

您将逻辑包装在另一个DI可注入服务中:IDocumentPreprocessorFactory。在那里,您为IDocumentPreprocessor实现注入工厂方法。

public interface IDocumentPreprocessorFactory
{
    IDocumentPreprocessor CreateDocumentPreprocessor(DocType docType);
}

public class DocumentPreprocessorFactory : IDocumentPreprocessorFactory
{
    private readonly Func<TxtPreprocessor> createTxtPreprocessor;

    private readonly Func<DocPreprocessor> createDocPreprocessor;

    public DocumentPreprocessorFactory(
        Func<TxtPreprocessor> createTxtPreprocessor,
        Func<DocPreprocessor> createDocPreprocessor)
    {
        this.createTxtPreprocessor = createTxtPreprocessor;
        this.createDocPreprocessor = createDocPreprocessor;
    }

    public IDocumentPreprocessor CreateDocumentPreprocessor(DocType docType)
    {
        switch (docType)
        {
            case DocType.Txt:
                return this.createTxtPreprocessor();
            case DocType.Doc:
                return this.createDocPreprocessor();
            default:
                throw new...
        }
    }
}

您现在必须使用工厂方法的注册扩展DI设置。我还没有使用Core的DI,但我相信它可能看起来像这样

services.AddSingleton<Func<DocPreprocessor>>(ctx => () => ctx.GetService<DocPreprocessor());
services.AddSingleton<Func<TxtPreprocessor>>(ctx => () => ctx.GetService<TxtPreprocessor());

答案 1 :(得分:1)

这可以帮到你..

        // object lifetime transient or others.. determine according to your needs
        services.AddTransient<TxtPreprocessor>();
        services.AddTransient<DocPreprocessor>();
        services.AddTransient(processorFactory =>
        {
            Func<DocType, IDocumentPreprocessor> factoryFunc = docType =>
            {
                switch (docType)
                {
                    case DocType.Txt:
                        return processorFactory.GetService<TxtPreprocessor>();
                    default:
                        return processorFactory.GetService<DocPreprocessor>();// DocPreprocessor is defult
                }
            };
            return factoryFunc;
        });

在任何已注册的课程中使用..

public class AnyClass
{
    private readonly IDocumentPreprocessor _documentProcessor;

    public AnyClass(Func<DocType, IDocumentPreprocessor> factoryFunc)
    {
        _documentProcessor =  factoryFunc(DocType.Doc);
    }
}

如果需要,可以使用工厂类封装此函数