Structuremap - how to register certain types in certain layers

I use the DSL registry example to configure the structure of the structure. But at the same time, all my registered types are available in all layers of my application, where I add a link to the structural map. I do not want my business layer to know anything about my data access level and vice versa. How to get a structure structure for registering only certain types for each of my layers?

Here is the code in my global.asax file:

ObjectFactory.Initialize(x => { x.AddRegistry<RegistryIOC>(); }); 

And here is my RegistryIOC class:

 public class RegistryIOC : SMRegistry { public RegistryIOC() { For<IProfileService>.Use<ProfileService>(); For<IProctorService>().Use<ProctorService>(); //Business Logic Objects For<IQual>().Use<Qual>(); For<ITest>().Use<Test>(); For<IBoldface>().Use<Boldface>(); For<ITrainingPlan>().Use<TrainingPlan>(); For<IUnit>().Use<Unit>(); //Data Transfer Objects For<IGenericDTO>().Use<GenericDTO>(); For<IProfileDTO>().Use<ProfileDTO>(); For<IQualDTO>().Use<QualDTO>(); For<IPermissionDTO>().Use<PermissionDTO>(); //Repository Objects For<IProctorRepository>().Use<ProctorRepository>(); For<IQualsRepository>().Use<QualsRepository>(); For<ITestRepository>().Use<TestRepository>(); For<IUnitRepository>().Use<UnitRepository>(); For<IUserRepository>().Use<UserRepository>(); } } 

Thanks for the help.

+6
source share
2 answers

I use reflection to accomplish this (and other) tasks. Let me show you how it works.

The first thing to do is to define an interface that allows us to identify classes that perform initialization tasks:

 public interface IConfigurationTask { void Configure(); } 

Next, create one or more classes that implement this interface. These classes will be distributed throughout your projects, which is another way of saying that you can put them โ€œwhere they belongโ€.

 public class RepositoryInitializer : IConfigurationTask { public void Configure() { // code that does relevant initialization goes here } } 

The last piece of the puzzle is to find classes that implement the IConfigurationTask interface, create an instance from them, and execute the Configure method. This is the purpose of the ConfigurationTaskRunner:

 public static class ConfigurationTaskRunner { public static void Execute( params string[] assemblyNames ) { var assemblies = assemblyNames.Select( Assembly.Load ).Distinct().ToList(); Execute( assemblies ); } public static void Execute( IEnumerable<Assembly> assemblies ) { var tasks = new List<IConfigurationTask>(); assemblies.ForEach( a => tasks.AddRange( a.CreateInstances<IConfigurationTask>() ) ); tasks.ForEach( t => t.Configure() ); } } 

The code here uses a custom extension to iterate over all the items in the list and perform an action for each item (ForEach method). I also use the reflection library to do the task of finding and instantiating instances with a single layer (CreateInstances method), but you could achieve the same thing using simple reflection (as shown in the code below).

 public static IList<T> CreateInstances<T>( this Assembly assembly ) { var query = from type in assembly.GetTypes().Where( t => typeof(T).IsAssignableFrom( t ) && typeof(T) != t ) where type.IsClass && ! type.IsAbstract && type.GetConstructor( Type.EmptyTypes ) != null select (T) Activator.CreateInstance( type ); return query.ToList(); } 

The final piece of the puzzle is launching the execution of the ConfigurationTaskRunner. For example, in a web application, this will be in Application_Start in Global.asax:

 // pass in the names of the assemblies we want to scan, hardcoded here as an example ConfigurationTaskRunner.Execute( "Foo.dll", "Foo.Domain.dll" ); 

I also found it useful with the IPrioritizedConfigurationTask derivative (which adds the Priority property) to ensure that tasks are ordered correctly before they are executed. This is not shown in the above code example, but it is pretty trivial to add.

Hope this helps!

+3
source

You can create and configure several independent Container instances without using a static ObjectFactory - see this article . It will be your responsibility to provide the right containers for the right layers.

By the way, how do you want to handle interlayer communication? Is it not so difficult? I would prefer to separate the registries (possibly to separate the assemblies) and keep them untied "manually" instead of providing isolation at the infrastructure level.

0
source

Source: https://habr.com/ru/post/900800/


All Articles