Avoiding IoC Container Connection

I am developing an extensible framework using DI and IoC. Users should be able to redefine existing functions within the framework by dropping their own implementations into the container.

How can I let users do this without requiring them to know which IoC container I use?

My current halfway solution is to structure my assemblies as follows:

1) Define abstract assemblies containing only interfaces.

2) Define specific assemblies that implement these interfaces. Users can define their own to override existing functions.

3) Define container bindings in separate assemblies; that is, one linking assembly per specific node.

This means that specific assemblies are not associated with a specific IoC container, and they will be closed against modification if I use a different container. However, users still need to know which container my infrastructure uses to write assembly assemblies, and they will need to release new binding assemblies if I change the IoC container (i.e., From Ninject to Spring).

Did I miss something?

+6
source share
5 answers

The Common Service Locator is one approach, but it contains only methods for solving, not for registering.

You can see how this is implemented in the agatha-rrsl project . Here's a more complete description here , but in short:

  • define an agnostic interface for registering and resolving types
  • provide implementations for different containers (or allow users to submit implementations)

Caution: you probably cannot directly use your container in your library.

+1
source

Write down loosely coupled code . Applications must be container dependent. The framework should not.

+9
source

The general approach is to abstract an container with a common service locator

The author of MvcExtensions quite successfully separated IoC.

+2
source

Two simple options: either provide your user with a dictionary where they can register type mappings, or alternatively simply provide them with a container interface that provides all the services that you think you will probably require and allow users to supply their own own packaged containers. Sorry if they don't fit your scenario, I use Unity first, so I don’t know if Ninject, etc. Come up with what Unity does not.

0
source

I solved this with the attribute and provide a scanner class that is used to search for all the implementations and interfaces that they provide.

public class ComponentAttribute : Attribute {} // class that should be registered in the container. [Component] public class MyService : IMyService {} // Contains information for each class that should be // registered in the container. public interface IContainerMapping { public Type ImplementationType {get;} public IEnumerable<T> ImplementedServices {get; } } public class ComponentProvider { public static IEnumerable<IContainerMapping> Find() { var componentType = typeof(ComponentAttribute); foreach (var type in Assembly.GetExecutingAssembly().GetTypes()) { if (type.GetCustomAttributes(componentType, false).Count == 0) continue; var mapping = new ContainerMapping(type); List<Type> interfaces new List<Type>(); foreach (var interfac in type.GetInterfaces()) { //only get our own interfaces. if (interface.Assembly != Assembly.GetExecutingAssembly()) continue; interfaces.Add(interfac); } mapping.ImplementedServices = interfaces; yield return mapping; } } } 

This solution gives the user great flexibility. It can provide its own solution using the [Component] attribute directly or using your solution.

What the user should do is something like:

 foreach (var mapping in ComponentProvider.Find()) myContainer.Register(mapping.ImplementationType).As(mapping.ImplementedServices); 

I usually create a turnkey solution by providing the MyProject.autofac project, which registers everything in my favorite container.

0
source

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


All Articles