How to use Unity DI to load an assembly with dependencies and then register internal elements

I have an asp.net mvc 3 web application that has plugin assemblies that implement system-dependent EF contexts and services.

For example, I have an assembly that looks like this in general:

System1Controller : IController // from System.Web.Mvc ISystem1Service { IList<System1Type> GetOperation(string something); } System1Service : ISystem1Service { private ISystem1Entities context; public System1Service(ISystem1Entities context) { this.context = context; } } ISystem1Entities { IDbSet<System1Type> Operations { get; set; } } System1Entities : DbContext, ISystem1Entities 

Using Unity Bootstrapper and calling Bootstrapper.Initialize () works with the following BuildUnityContainer () implementation

 private static IUnityContainer BuildUnityContainer() { var theContainer = new UnityContainer(); var connectionString = ConfigurationManager.ConnectionStrings["WebAppConnectionString"]; if (connectionString == null) { throw new ApplicationException("The ConnectionString is not defined."); } // register all your components with the container here // it is NOT necessary to register your controllers theContainer.RegisterType<ISystem1Entities, System1Entities>( new HierarchicalLifetimeManager(), new InjectionConstructor(connectionString.ConnectionString)); theContainer.RegisterType<ISystem1Service, System1Service>(); var factory = new UnityControllerFactory(theContainer); ControllerBuilder.Current.SetControllerFactory(factory); return theContainer; } 

I want to reorganize the bootloader so that I can load "unknown" in assembly-time assemblies, register the types that are contained in them, and allow the web application to access the controller, services, contexts as needed.

I looked at the Unity AutoRegistraion project, and it looks like I'm getting me in the implementation area that I want, but I don’t know how to implement the following idea:

 BootStrapper.BuildUnityConfiguration Initialize Container RegisterMyAssemblies() 

I want the RegisterMyAssemblies process to register a wildcard list of assemblies, and then start registering types in each individual assembly. Any suggestions?

+4
source share
2 answers

You should not try to use the main application loader (compound root) to configure these plugin assemblies, as this will be quite difficult. It is difficult to obtain the right, because the main program does not know which types to register, and for how long these types of life should be registered.

Instead, let each plug-in assembly have its own bootstrap method and pass an instance of the application container to this bootable boot module.

You can, for example, define the IBootstrapper interface in the main assembly and allow each plug-in assembly to implement this interface. For instance:

 public class System1Bootstrapper : IBootstrapper { void IBootstrapper.Bootstrap(IUnityContainer container) { var conString = ConfigurationManager .ConnectionStrings["WebAppConnectionString"]; if (conString == null) { throw new ApplicationException( "The ConnectionString is not defined."); } // register all your components with the container here // it is NOT necessary to register your controllers container.RegisterType<ISystem1Entities, System1Entities>( new HierarchicalLifetimeManager(), new InjectionConstructor(conString.ConnectionString)); container.RegisterType<ISystem1Service, System1Service>(); } } 

In your root application, you can simply add this code to register all types of plugins:

 var pluginBootstrappers = from Assembly assembly in BuildManager.GetReferencedAssemblies() from type in assembly.GetExportedTypes() where typeof(IBootstrapper).IsAssignableFrom(type) select (IBootstrapper)Activator.CreateInstance(type); pluginBootstrappers.ToList().ForEach(b => b.Bootstrap(container)); 
+5
source

This is admittedly a plugin, but take a look at my Unity Automapper on NuGet. This allows you to do just such things - you just provide it with a set of types or assembly names; it will automatically connect dependencies based on interfaces - specific mappings. It also works on internal types, so you can do the β€œright” DIP by opening your interfaces and providing them with internal interfaces.

0
source

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


All Articles