2009-02-27 10 views
4

Ich versuche Strukturkarte zu bekommen, um meine Controller korrekt zu erstellen, ich verwende DI, um einen INewsService in einen NewsController zu injizieren, und das ist der einzige Konstruktor, den ich habe.ASP.NET MVC, MVCContrib, Strukturkarte, wie funktioniert es als controllerfactory?

public class NewsController : Controller 
{ 
    private readonly INewsService newsService; 

    public NewsController(INewsService newsService) 
    { 
     this.newsService = newsService; 
    } 

    public ActionResult List() 
    { 
     var newsArticles = newsService.GetNews(); 
     return View(newsArticles); 
    } 
} 

und ich bin mit diesem Code den App starten

public class Application : HttpApplication 
{ 
    protected void Application_Start() 
    { 
     RegisterIoC(); 
     RegisterViewEngine(ViewEngines.Engines); 
     RegisterRoutes(RouteTable.Routes); 
    } 

    public static void RegisterIoC() 
    { 
     ObjectFactory.Initialize(config => { 
      config.UseDefaultStructureMapConfigFile = false; 
      config.AddRegistry<PersistenceRegistry>(); 
      config.AddRegistry<DomainRegistry>(); 
      config.AddRegistry<ControllerRegistry>(); 
     }); 
     DependencyResolver.InitializeWith(new StructureMapDependencyResolver()); 
     ControllerBuilder.Current.SetControllerFactory(typeof(IoCControllerFactory));    
    } 
} 

Aber Structuremap scheint nicht das INewsService injizieren zu wollen, und ich bekomme die Fehler Kein parameterlosen Konstruktor für dieses Objekt definiert .

Was habe ich verpasst?

Antwort

6

Ich verwende den "Default Conventions" -Mechanismus, den StructureMap bietet, um zu vermeiden, dass jede Schnittstelle einzeln konfiguriert werden muss. Unten ist der Code, den ich diese Arbeit zu machen verwenden:

Meine Global.asax diese Zeile in Application_Start hat (die die StructureMap Fabrik von MvcContrib verwendet):

protected void Application_Start() 
{ 
    RegisterRoutes(RouteTable.Routes); 
    ObjectFactory.Initialize(x => 
    { 
     x.AddRegistry(new RepositoryRegistry()); 
    }); 
    ControllerBuilder.Current.SetControllerFactory(typeof(StructureMapControllerFactory)); 
} 

Und sieht die RepositoryRegistry Klasse wie folgt:

public class RepositoryRegistry : Registry 
{ 

    public RepositoryRegistry() 
    { 
     Scan(x => 
     { 
      x.Assembly("MyAssemblyName"); 
      x.With<DefaultConventionScanner>(); 
     }); 

    } 

} 

die DefaultConventionScanner für Paare von Schnittstellen/Klassen sucht, die die nameing convention of ISomethingOrOther und SomethingOrOther folgen und ordnet automatisch die letztere als konkreter für die frühere Schnittstelle.

Wenn Sie nicht, dass die Standard-Konvention Mechanismus verwenden wollen, dann würden Sie Code in der Registry-Klasse hinzufügen explicity mit dieser Syntax jedes Ihrer Schnittstellen zu den konkreten Typen zuzuordnen:

ForRequestedType<ISomethingOrOther>().TheDefaultIsConcreteType<SomethingOrOther>(); 
+0

Danke!, Das hat mir sehr geholfen, ich konnte mein Problem umgehen :) –

+0

@Erv in welchem ​​Namensraum befindet sich Scan? Mir scheint eine Verwendung oder eine Referenz zu fehlen. – ahsteele

+0

In der Version, die wir verwenden (das ist 8 Monate veraltet - ich habe nicht untersucht, was sich kürzlich geändert hat), ist Scan eine Methode für die Registry-Basisklasse, von der RepositoryRegistry in dem Beispiel erbt. –

0

Sofern ich etwas nicht verpasse, sagen Sie StructureMap nicht, welcher konkrete Typ für INewsService zu verwenden ist. Sie müssen wie etwas hinzufügen:

TheConcreteTypeOf<INewsService>.Is<MyConcreteNewsService>(); 

Ich weiß nicht, die genaue Syntax aus der Spitze von meinem Kopf, aber das ist, was du verpasst. Sobald Sie dies angeben, wird es wissen, welche Instanz des INewsService in den Controller injiziert werden soll.

+0

Ich füge alle richtigen Zuordnungen in Registrys, wie INewsService, so sollte es nicht sein, dass das das Problem verursacht. –

+0

Ich sehe nicht den Code, wo Sie es instanziieren. – Micah

+0

Können Sie den Code in den Registries anzeigen? – Micah

0

ASP. NET MVC instanziiert gegenwärtig Controller, die den parameterlosen Standardkonstruktor verwenden, der jegliche auf Konstruktoren basierende Abhängigkeitsinjektion ausschließt. Um das zu tun, müssen Sie wirklich das Projekt MvcContrib verwenden, das eingebaute Unterstützung für StructureMap (und Castle/Spring.NET/Unity) hat, obwohl die aktuelle Dokumentation nicht existiert (wörtlich, Sie erhalten eine Stub-Wiki-Seite, kein gutes Zeichen). Das Codebeispiel von Erv Walter in diesem Thread zeigt, wie die Integration von StructureMap eingerichtet wird.

Verwandte Themen