2017-05-06 13 views
-1

出力をpdfとして出力するカスタムフォーマッタを1つ作成しました。次のスレッドで詳細を参照してください:それは答えあたりとして正常に動作している複数のクラスを持つカスタムフォーマッタへの依存性注入

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

ここで依存性注入でどのように指定できますか。コンテキストバインディングについて読んだところ、問題が解決したと思います。

私はちょうど以下のような注射を追加しました。 WEBAPIの設定で

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

 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構成コード。コンフィグで

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

また、フォーマッタはnullです。何か逃した?

+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

関連する問題