2017-05-06 29 views
-1

我创建了一个自定义格式化程序,以PDF格式输出。请以下螺纹参考更多详细信息:向具有多个类的自定义格式化程序的依赖注入

Dependency Injection to CustomFormatter

这是工作的罚款为每答案。但现在我有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类只有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); 

现在格式化程序也是空的。什么错过了?

+0

请让这个[最小的,完整的和可核查的示例](https://stackoverflow.com/help/mcve]),而不只是依靠链接到你的老问题。 – BatteryBackupUnit

+0

另请参阅https://meta.stackexchange.com/questions/141823/why-is-cross-posting-wrong-on-an-external-site – BatteryBackupUnit

+0

肯定感谢通知 – Akhil

回答

1

更新报告接口,以便能够识别模型,它可以处理

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(); 
+0

我认为还有一些改进的空间: 'typeisIPdf','typeisIPdfCollection','CanHandle'和'Create'中非常类似的代码。 将一个非特定类型'object'映射到一个特定类型('Bill','Purchase' ...)一次又一次地重复。 – BatteryBackupUnit