2017-05-06 1 views
-1

J'ai créé un formateur personnalisé pour donner une sortie en format pdf. S'il vous plaît se référer plus de détails dans le fil suivant:Injection de dépendances vers un formateur personnalisé avec plusieurs classes

Dependency Injection to CustomFormatter

Il fonctionne bien selon la réponse. Mais maintenant j'ai 2 rapports comme ci-dessous;

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

Ici, comment puis-je spécifier dans l'injection de dépendance. J'ai lu sur la liaison de contexte et il pense que cela a résolu le problème.

J'ai juste ajouté l'injection comme ci-dessous;

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

Dans la configuration WebAPI,

 var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter)); 
     config.Formatters.Add(formatter); 

Lors de l'exécution, je suis toujours nulle dans formatter. S'il vous plaît aidez-moi à trouver l'erreur

Mise à jour:

J'utilisé ninject.extensions.factory. J'ai changé mon code comme ci-dessous;

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

Maintenant, mon BillReport et PurchaseReport implémente l'interface IReport. La classe Pdfmapper possède également l'interface IReport uniquement.

Le code de configuration de ninject comme ci-dessous;

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

Dans la configuration, formatter personnalisé zone en ajoutant à nouveau i se formatter comme nulle

var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter)); 
    config.Formatters.Add(formatter); 

Nouvelle mise à jour:

Ma configuration ninject:

kernel.Bind<IReport>().To<PurchaseReport>().InRequestScope(); 
      kernel.Bind<IReport>().To<BillReport>().InRequestScope(); 
      kernel.Bind<IPdfFactory>().To<PdfFactory>().InRequestScope(); 
      kernel.Bind<PdfMediaTypeFormatter>().ToSelf(); 

Dans webapi config:

var formatter = (PdfMediaTypeFormatter)config.DependencyResolver.GetService(typeof(PdfMediaTypeFormatter)); 
    config.Formatters.Add(formatter); 

maintenant aussi formatter est null. quelque chose a manqué?

+0

S'il vous plaît font un [exemple minimal, complet et vérifiable] (https://stackoverflow.com/help/mcve]) sans compter uniquement sur un lien vers votre ancienne question. – BatteryBackupUnit

+0

Aussi s'il vous plaît voir https://meta.stackexchange.com/questions/141823/why-is-cross-posting-wrong-on-an-external-site – BatteryBackupUnit

+0

bien sûr pour la notification – Akhil

Répondre

1

mise à jour l'interface du rapport pour pouvoir identifier quels modèles il peut gérer

public interface IReport { 
    bool CanHandle(object model); 
    Task<MemoryStream> Create(object model); 
} 

En supposant quelques exemples de modèles comme celui-ci. Les implémentations de rapport auraient quelque chose de similaire à la logique dans le formateur

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

L'usine serait maintenant juste besoin d'être au courant de toutes les mises en œuvre de IReport.Il serait alors obtenir le rapport qui peut gérer le modèle fourni et exécuter la fonction désirée

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

L'avantage d'utiliser cette approche de l'abstraction est que vous n'avez même pas mettre à jour le formatter et toutes les modifications sont apportées sur l'autre dépendances et problèmes de mise en œuvre.

Assurez-vous d'enregistrer toutes les implémentations IReport afin qu'elles soient transmises au IPdfFactory lorsqu'elles sont résolues.

Se référant à la documentation Multi injection

kernel.Bind<IReport>().To<PurchaseReport>(); 
kernel.Bind<IReport>().To<BillReport>(); 
kernel.Bind<IPdfFactory>().To<PdfFactory>(); 
kernel.Bind<PdfMediaTypeFormatter>().ToSelf(); 
+0

Je pense qu'il y a une certaine marge d'amélioration: Code très similaire dans 'typeisIPdf',' typeisIPdfCollection', 'CanHandle' et' Create'. Le mappage d'un type 'object' de type non spécifique à un type spécifique (' Bill', 'Purchase' ...) est répété encore et encore. – BatteryBackupUnit