我有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使用?
答案 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);
}
}
如果需要,可以使用工厂类封装此函数