I have Asp.net Core project with default DI realization. So I get BL-services instances, repositories, EF-context by DI. I have abstract method that returns certain type by parameter.
IDocumentPreprocessor CreateDocumentPreprocessor(DocType docType)
{
switch (docType)
{
case DocType.Txt:
return new TxtPreprocessor(_context, _docRepository);
case DocType.Doc:
return new DocPreprocessor(_docRepository);
default:
throw new ...
}
}
I don't like here direct creation of instance by "new". But I'm not sure if it's possible to pass this logic to DI. So the question - how to refactor it to DI usage?
You wrap the logic in yet another DI-injectable service: an IDocumentPreprocessorFactory
. There you inject factory methods for IDocumentPreprocessor
implementations.
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...
}
}
}
You must now extend your DI setup with the registrations of the factory methods. I have not used Core's DI yet, but I believe it might look something like this
services.AddSingleton<Func<DocPreprocessor>>(ctx => () => ctx.GetService<DocPreprocessor());
services.AddSingleton<Func<TxtPreprocessor>>(ctx => () => ctx.GetService<TxtPreprocessor());
this is can be help you..
// 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;
});
usage in any registered class..
public class AnyClass
{
private readonly IDocumentPreprocessor _documentProcessor;
public AnyClass(Func<DocType, IDocumentPreprocessor> factoryFunc)
{
_documentProcessor = factoryFunc(DocType.Doc);
}
}
you can encapsulate this function with factory class, if you want
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.