使用多个 Class 对自定义格式化程序进行依赖注入
Dependency Injection to Custom Formatter with Multiple Class
我创建了一个自定义格式化程序来提供 pdf 格式的输出。请参考以下线程中的更多详细信息:
根据答案,它工作正常。但现在我有 2 份报告,如下所示;
public interface IPdfFactory {
MemoryStream Create(object model);
}
public class BillReport: IPdfFactory {
private readonly IBusinessLogic _logic;
public PdfFactory(IBusinessLogic logic) {
this._logic = logic;
}
public MemoryStream Create(object model) {
var stream = new MemoryStream();
//...Pdf generation code
//call data update
_logic.update(model);
return stream;
}
}
public class PurchaseReport: IPdfFactory {
private readonly IBusinessLogic _logic;
public PdfFactory(IBusinessLogic logic) {
this._logic = logic;
}
public MemoryStream Create(object model) {
var stream = new MemoryStream();
//...Pdf generation code
//call data update
_logic.update(model);
return stream;
}
}
这里我如何在依赖注入中指定。我读到了上下文绑定,它认为它解决了这个问题。
我只是像下面这样添加了注入;
kernel.Bind<IPdfFactory>().To<BillReport>().When(request => request.Target.Member.Name.StartsWith("Bill"));
kernel.Bind<IPdfFactory>().To<PurchaseReport>().When(request => request.Target.Member.Name.StartsWith("Purchase"));
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();
在 WebApi 配置中,
var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter));
config.Formatters.Add(formatter);
当运行时,我总是在格式化程序中得到空值。请帮我找出错误
更新:
我用了ninject.extensions.factory。我更改了如下代码;
public interface IPdfFactory
{
IReport GetPurchaseReport();
IReport GetBillReport();
}
public interface IReport
{
Task<MemoryStream> Create(object model);
}
现在我的 BillReport 和 PurchaseReport 实现了 IReport 接口。另外 Pdfmapper class 只有 IReport 接口
ninject配置代码如下;
kernel.Bind<IReport>().To<PurchaseReport>().Named("PurchaseReport");
kernel.Bind<IReport>().To<BillReport>().Named("BillReport");
kernel.Bind<IPdfFactory>().ToFactory();
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();
在配置中,自定义格式化程序再次添加区域我得到格式化程序为空
var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter));
config.Formatters.Add(formatter);
新更新:
我的ninject配置:
kernel.Bind<IReport>().To<PurchaseReport>().InRequestScope();
kernel.Bind<IReport>().To<BillReport>().InRequestScope();
kernel.Bind<IPdfFactory>().To<PdfFactory>().InRequestScope();
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();
在 webapi 配置中:
var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter));
config.Formatters.Add(formatter);
现在 formatter 也为 null 。有什么遗漏吗?
更新报告界面以识别它可以处理的模型
public interface IReport {
bool CanHandle(object model);
Task<MemoryStream> Create(object model);
}
假设一些示例模型是这样的。
class BillModel : IPdf {
//...
}
class PurchaseModel : IPdf {
//...
}
报表实现与格式化程序中的逻辑有些相似。
public class BillReport : IReport {
Func<Type, bool> typeisIPdf = (type) => typeof(BillModel).IsAssignableFrom(type);
Func<Type, bool> typeisIPdfCollection = (type) => typeof(IEnumerable<BillModel>).
IsAssignableFrom(type);
private readonly IBusinessLogic _logic;
public BillReport(IBusinessLogic logic) {
this._logic = logic;
}
public bool CanHandle(object model) {
if (model == null) return false;
var type = model.GetType();
return typeisIPdf(type) || typeisIPdfCollection(type);
}
public Task<MemoryStream> Create(object model) {
var stream = new MemoryStream();
if (CanHandle(model.GetType())) {
//...Pdf generation code
//call data update
_logic.update(model);
}
return Task.FromResult(stream);
}
}
public class PurchaseReport : IReport {
Func<Type, bool> typeisIPdf = (type) => typeof(PurchaseModel).IsAssignableFrom(type);
Func<Type, bool> typeisIPdfCollection = (type) => typeof(IEnumerable<PurchaseModel>).
IsAssignableFrom(type);
private readonly IBusinessLogic _logic;
public PurchaseReport(IBusinessLogic logic) {
this._logic = logic;
}
public bool CanHandle(object model) {
if (model == null) return false;
var type = model.GetType();
return typeisIPdf(type) || typeisIPdfCollection(type);
}
public Task<MemoryStream> Create(object model) {
var stream = new MemoryStream();
if (CanHandle(model.GetType())) {
//...Pdf generation code
//call data update
_logic.update(model);
}
return Task.FromResult(stream);
}
}
工厂现在只需要了解 IReport
的所有实现。然后它将获得可以处理提供的模型并执行所需功能的报告
public class PdfFactory : IPdfFactory {
private IEnumerable<IReport> reports;
public PdfFactory(IReport[] reports) {
this.reports = reports;
}
public Task<MemoryStream> Create(object model) {
var report = reports.FirstOrDefault(r => r.CanHandle(model));
if (report != null) {
return report.Create(model);
}
return Task.FromResult<MemoryStream>(null);
}
}
使用这种抽象方法的优点是您甚至不必更新格式化程序,所有更改都是针对其他依赖项和实现问题进行的。
确保注册所有 IReport
实现,以便在解析时将它们传递给 IPdfFactory
。
参考 Multi injection 文档
kernel.Bind<IReport>().To<PurchaseReport>();
kernel.Bind<IReport>().To<BillReport>();
kernel.Bind<IPdfFactory>().To<PdfFactory>();
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();
我创建了一个自定义格式化程序来提供 pdf 格式的输出。请参考以下线程中的更多详细信息:
根据答案,它工作正常。但现在我有 2 份报告,如下所示;
public interface IPdfFactory {
MemoryStream Create(object model);
}
public class BillReport: IPdfFactory {
private readonly IBusinessLogic _logic;
public PdfFactory(IBusinessLogic logic) {
this._logic = logic;
}
public MemoryStream Create(object model) {
var stream = new MemoryStream();
//...Pdf generation code
//call data update
_logic.update(model);
return stream;
}
}
public class PurchaseReport: IPdfFactory {
private readonly IBusinessLogic _logic;
public PdfFactory(IBusinessLogic logic) {
this._logic = logic;
}
public MemoryStream Create(object model) {
var stream = new MemoryStream();
//...Pdf generation code
//call data update
_logic.update(model);
return stream;
}
}
这里我如何在依赖注入中指定。我读到了上下文绑定,它认为它解决了这个问题。
我只是像下面这样添加了注入;
kernel.Bind<IPdfFactory>().To<BillReport>().When(request => request.Target.Member.Name.StartsWith("Bill"));
kernel.Bind<IPdfFactory>().To<PurchaseReport>().When(request => request.Target.Member.Name.StartsWith("Purchase"));
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();
在 WebApi 配置中,
var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter));
config.Formatters.Add(formatter);
当运行时,我总是在格式化程序中得到空值。请帮我找出错误
更新:
我用了ninject.extensions.factory。我更改了如下代码;
public interface IPdfFactory
{
IReport GetPurchaseReport();
IReport GetBillReport();
}
public interface IReport
{
Task<MemoryStream> Create(object model);
}
现在我的 BillReport 和 PurchaseReport 实现了 IReport 接口。另外 Pdfmapper class 只有 IReport 接口
ninject配置代码如下;
kernel.Bind<IReport>().To<PurchaseReport>().Named("PurchaseReport");
kernel.Bind<IReport>().To<BillReport>().Named("BillReport");
kernel.Bind<IPdfFactory>().ToFactory();
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();
在配置中,自定义格式化程序再次添加区域我得到格式化程序为空
var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter));
config.Formatters.Add(formatter);
新更新:
我的ninject配置:
kernel.Bind<IReport>().To<PurchaseReport>().InRequestScope();
kernel.Bind<IReport>().To<BillReport>().InRequestScope();
kernel.Bind<IPdfFactory>().To<PdfFactory>().InRequestScope();
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();
在 webapi 配置中:
var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter));
config.Formatters.Add(formatter);
现在 formatter 也为 null 。有什么遗漏吗?
更新报告界面以识别它可以处理的模型
public interface IReport {
bool CanHandle(object model);
Task<MemoryStream> Create(object model);
}
假设一些示例模型是这样的。
class BillModel : IPdf {
//...
}
class PurchaseModel : IPdf {
//...
}
报表实现与格式化程序中的逻辑有些相似。
public class BillReport : IReport {
Func<Type, bool> typeisIPdf = (type) => typeof(BillModel).IsAssignableFrom(type);
Func<Type, bool> typeisIPdfCollection = (type) => typeof(IEnumerable<BillModel>).
IsAssignableFrom(type);
private readonly IBusinessLogic _logic;
public BillReport(IBusinessLogic logic) {
this._logic = logic;
}
public bool CanHandle(object model) {
if (model == null) return false;
var type = model.GetType();
return typeisIPdf(type) || typeisIPdfCollection(type);
}
public Task<MemoryStream> Create(object model) {
var stream = new MemoryStream();
if (CanHandle(model.GetType())) {
//...Pdf generation code
//call data update
_logic.update(model);
}
return Task.FromResult(stream);
}
}
public class PurchaseReport : IReport {
Func<Type, bool> typeisIPdf = (type) => typeof(PurchaseModel).IsAssignableFrom(type);
Func<Type, bool> typeisIPdfCollection = (type) => typeof(IEnumerable<PurchaseModel>).
IsAssignableFrom(type);
private readonly IBusinessLogic _logic;
public PurchaseReport(IBusinessLogic logic) {
this._logic = logic;
}
public bool CanHandle(object model) {
if (model == null) return false;
var type = model.GetType();
return typeisIPdf(type) || typeisIPdfCollection(type);
}
public Task<MemoryStream> Create(object model) {
var stream = new MemoryStream();
if (CanHandle(model.GetType())) {
//...Pdf generation code
//call data update
_logic.update(model);
}
return Task.FromResult(stream);
}
}
工厂现在只需要了解 IReport
的所有实现。然后它将获得可以处理提供的模型并执行所需功能的报告
public class PdfFactory : IPdfFactory {
private IEnumerable<IReport> reports;
public PdfFactory(IReport[] reports) {
this.reports = reports;
}
public Task<MemoryStream> Create(object model) {
var report = reports.FirstOrDefault(r => r.CanHandle(model));
if (report != null) {
return report.Create(model);
}
return Task.FromResult<MemoryStream>(null);
}
}
使用这种抽象方法的优点是您甚至不必更新格式化程序,所有更改都是针对其他依赖项和实现问题进行的。
确保注册所有 IReport
实现,以便在解析时将它们传递给 IPdfFactory
。
参考 Multi injection 文档
kernel.Bind<IReport>().To<PurchaseReport>();
kernel.Bind<IReport>().To<BillReport>();
kernel.Bind<IPdfFactory>().To<PdfFactory>();
kernel.Bind<PdfMediaTypeFormatter>().ToSelf();