Domanda

Ho una configurazione strutturemap che mi fa grattare la testa. Ho una classe concreta che richiede un elemento dell'interfaccia utente che richiede una classe di convalida interfacciata. Voglio che la classe esterna in cemento ottenga l'elemento predefinito dell'interfaccia utente, ma ottenga un oggetto di convalida specifico della classe concreta. Qualcosa del genere:

class MyView 
{
   IPrompt prompt
}

class GenericPrompt : IPrompt
{
   IValidator validator
}

class MyValidator : IValidator
{
   bool Validate() {}
}

Come posso configurare structuremap con il DSL del Registro di sistema per utilizzare MyValidator solo quando creo dipendenze per MyView. (E presumibilmente usando BobsValidator quando si creano dipendenze per BobsView)

È stato utile?

Soluzione

Stai ricevendo MyView (e BobsView) dal contenitore? Possiamo presumere che prenderanno tutti un'istanza di IPrompt?

Un approccio sarebbe quello di registrare tutti i tuoi validatori con un nome che corrisponda ai nomi della tua vista. Potresti implementare il tuo scanner di tipi che rimuove semplicemente il suffisso Validator:

public class ValidatorScanner : ITypeScanner
{
    public void Process(Type type, PluginGraph graph)
    {
        if (!typeof (IValidator).IsAssignableFrom(type)) return;
        var validatorName = type.Name.Replace("Validator", "");
        graph.AddType(typeof(IValidator), type, validatorName);
    }
}

Ora, se supponi che un IPrompt sia sempre richiesto da una Vista che segue quella convenzione di denominazione, il tuo registro potrebbe apparire come:

public class ValidatorRegistry : Registry
{
    public ValidatorRegistry()
    {
        Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.With<ValidatorScanner>();
        });

        ForRequestedType<IPrompt>().TheDefault.Is.ConstructedBy(ctx =>
        {
            var viewName = ctx.Root.RequestedType.Name.Replace("View", "");
            ctx.RegisterDefault(typeof(IValidator), ctx.GetInstance<IValidator>(viewName));
            return ctx.GetInstance<GenericPrompt>();
        });
    }
}

Per recuperare la tua vista con l'apposito validatore, dovresti richiedere il tipo concreto:

var view = container.GetInstance<MyView>();

Nota che funzionerà solo se stai recuperando la tua vista con una chiamata diretta al container (posizione del servizio), poiché dipende da " Root.RequestedType " ;. A seconda di come prevedi di ottenere le tue visualizzazioni, potresti essere in grado di camminare su BuildStack cercando una vista (invece di supporre che sia sempre root).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top