2009-06-10 9 views
7

Estoy usando mvc.net con StructureMap para escanear y registrar todos los repositorios y servicios por mí. Ahora quiero registrarme y almacenar en caché por Singleton. ¿Como lo puedo hacer?¿Cómo puedo configurar Structuremap para escanear automáticamente el tipo en ensamblado y caché por Singleton?

IContainer container = new Container(x => { 
      // Register Repositories and Services 
      x.Scan(y => { 
       y.AssemblyContainingType<SomeRepository>(); 
       y.AssemblyContainingType<SomeService>(); 

       y.IncludeNamespaceContainingType<SomeRepository>(); 
       y.IncludeNamespaceContainingType<SomeService>(); 
      }); 

      // Register Controllers 
      x.Scan(y => { 
       y.TheCallingAssembly(); 
       y.AddAllTypesOf<IController>().NameBy(type => type.Name.Replace("Controller", "")); 
      }); 
     }); 

Respuesta

19

Al utilizar la nueva API en 2.6, ITypeScanner está en desuso. Esto debería implementarse como una convención en su lugar. Un ejemplo sencillo es que desea registrar una convención que todos los tipos de una interfaz en particular son un producto único:

Scan(a => 
    { 
     a.AssemblyContainingType<IMyPluginType>(); 
     a.With(new SingletonConvention<IMyPluginType>()); 
     a.AddAllTypesOf<IMyPluginType>(); 
    }); 

continuación:

internal class SingletonConvention<TPluginFamily> : IRegistrationConvention 
    { 
     public void Process(Type type, Registry registry) 
     { 
      if (!type.IsConcrete() || !type.CanBeCreated() || !type.AllInterfaces().Contains(typeof(TPluginFamily))) return; 

      registry.For(typeof(TPluginFamily)).Singleton().Use(type); 
     } 
    } 
+0

+1 BTW, no es necesario llamar a.AddAllTypesOf (); en Escanear() como SingletonConvention.Process() registrará el tipo (s). – ozczecho

+0

¿Por qué necesito esas 3 líneas en 'Scan'? ¿Cuál es la diferencia entre 'a.With (new SingletonConvention ());' y 'a.AddAllTypesOf ();'? ¿Son esos dos realmente necesarios? Y si tengo otra interfaz, ¿necesito usar ambas líneas nuevamente? – tyron

+0

excesivamente detallado, pero funcionó como un campeón. Realmente creo que si la declaración debería ser utilizada, pero no voy a cambiar la API. Después de decir que no voy a cambiar la API, todavía no significa que no puedo hacerlo mejor –

2

Tendrá que aplicar el ITypeScanner similar a lo que Jeremy Miller describe en http://codebetter.com/blogs/jeremy.miller/archive/2009/01/20/create-your-own-auto-registration-convention-with-structuremap.aspx

Así que para sus controladores, por ejemplo, que cambiaría de que la exploración de llamada a ser:

x.Scan(y => { 
    y.TheCallingAssembly(); 
    y.With<MyNewTypeScanner>(); 
}); 

entonces me gustaría definir una clase en otro lugar que parecía algo como esto:

public class MyNewTypeScanner: ITypeScanner 
{ 
    //This method is responsible for determining if a type should be registered 
    // and then passing it to RegisterType() if so 
    public void Process(Type type, PluginGraph graph) 
    { 
     //At this point you would probably just test to see if type is IController 
     //but you can get more sophisticated without too much headache. 

     this.RegisterType(graph, type); 
    } 


    private void RegisterType(PluginGraph graph, Type implementingType) 
    { 
     //The argument passed to FindFamily must be the type/class that will be requested out of SM 
     var family = graph.FindFamily(implementingType); 

     family.AddType(implementingType); 
     family.SetScopeTo(InstanceScope.Singleton); 
    } 
} 

Esto debería hacer el truco para usted.

0

Ampliando la respuesta de @Eric Hauser crear una más fácilmente utilizables solución

public abstract class TypedRegistrationConvention<TPluginFamily> 
             : IRegistrationConvention 
{ 
    public virtual void Process(Type type, Registry registry) 
    { 
     if (!type.IsConcrete() 
      || !type.CanBeCreated() 
      || !type.AllInterfaces().Contains(typeof (TPluginFamily))) 
      return; 

     ApplyConvention(type, registry); 
    } 

    public abstract void ApplyConvention(Type type, Registry registry); 
} 

con esta clase de base establecida una vez, a continuación, puede aplicar los convenios sin tener que ensuciar alrededor con el código de tipo de cheques.

public class SingletonConvention<TPluginFamily> 
           : TypedRegistrationConvention<TPluginFamily> 
{ 
    public override void ApplyConvention(Type type, Registry registry) 
    { 
     registry.For(typeof (TPluginFamily)).Singleton().Use(type); 
    } 
} 

Clase mucho más simple al final.

Cuestiones relacionadas