多类的自定义格式化程序的依赖注入

时间:2017-05-06 03:39:03

标签: c# dependency-injection asp.net-web-api2 ninject

我创建了一个自定义格式化程序,以输出为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);

运行时,我总是在格式化程序中为null。请帮我找错误

更新

我使用了ninject.extensions.factory。我改变了我的代码,如下所示;

public interface IPdfFactory
{
    IReport GetPurchaseReport();
    IReport GetBillReport();
}
public interface IReport
{
    Task<MemoryStream> Create(object model);
}

现在我的BillReport和PurchaseReport实现了IReport接口。此外,Pdfmapper类仅具有IReport接口

ninject cofiguration代码如下;

    kernel.Bind<IReport>().To<PurchaseReport>().Named("PurchaseReport");
    kernel.Bind<IReport>().To<BillReport>().Named("BillReport");
    kernel.Bind<IPdfFactory>().ToFactory();
    kernel.Bind<PdfMediaTypeFormatter>().ToSelf();

在配置中,再次添加自定义格式化程序区域,格式化程序为null

    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);

现在格式化程序也为null。什么错过了?

1 个答案:

答案 0 :(得分: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();