How to set up the Unity Registration Convention?

With the map structure, you can register an agreement that allows you to not only customize the type, but also intervene when creating the object. How can I do this with Unity.

public class SettingsRegistration : IRegistrationConvention { public void Process(Type type, Registry registry) { if (!type.IsAbstract && typeof(ISettings).IsAssignableFrom(type)) { registry.For(type).Use(x => { var svc = x.GetInstance<ISettingService>(); return svc.LoadSetting(type); }); } } } 
+5
source share
1 answer

You can do this using a combination of Unity Convention Registration and InjectionFactory . I see three common implementation options, although I'm sure there are more ...


Option 1

Register all types at once if inline conditions are specified in a lambda expression. Although it doesn't scale very well if you register many types with many user registrations ...

 container.RegisterTypes( AllClasses.FromLoadedAssemblies(), WithMappings.FromAllInterfaces, WithName.Default, WithLifetime.Transient, type => { // If settings type, load the setting if (!type.IsAbstract && typeof (ISettings).IsAssignableFrom(type)) { return new[] { new InjectionFactory((c, t, n) => { var svc = (ISettings) c.Resolve(t); return svc.LoadSetting(t); }) }; } // Otherwise, no special consideration is needed return new InjectionMember[0]; }); 

Option 2

Register only ISettings types and supply some useful helper methods. You will need to call container.RegisterTypes several times, but it is much more readable ...

 container.RegisterTypes( AllClasses.FromLoadedAssemblies().IsSetting(), WithMappings.FromAllInterfaces, WithName.Default, WithLifetime.Transient, SettingsRegistration.InjectionMembers); ... public static class SettingsRegistration { public static IEnumerable<Type> IsSetting(this IEnumerable<Type> types) { return types.Where(type => !type.IsAbstract && typeof (ISettings).IsAssignableFrom(type)); } public static IEnumerable<InjectionMember> InjectionMembers(Type type) { return new[] {new InjectionFactory(LoadSetting)}; } public static ISettings LoadSetting(IUnityContainer container, Type type, string name) { var svc = (ISettings) container.Resolve(type, name); return svc.LoadSetting(type); } } 

Option 3

Or you can create a class derived from RegistrationConvention and let this class make all registration decisions ...

 container.RegisterTypes(new SettingsRegistrationConvention( AllClasses.FromLoadedAssemblies())); ... public class SettingsRegistrationConvention : RegistrationConvention { private readonly IEnumerable<Type> _scanTypes; public SettingsRegistrationConvention(IEnumerable<Type> scanTypes) { if (scanTypes == null) throw new ArgumentNullException("scanTypes"); _scanTypes = scanTypes; } public override IEnumerable<Type> GetTypes() { return _scanTypes.Where(type => !type.IsAbstract && typeof (ISettings).IsAssignableFrom(type)); } public override Func<Type, IEnumerable<Type>> GetFromTypes() { return WithMappings.FromAllInterfaces; } public override Func<Type, string> GetName() { return WithName.Default; } public override Func<Type, LifetimeManager> GetLifetimeManager() { return WithLifetime.Transient; } public override Func<Type, IEnumerable<InjectionMember>> GetInjectionMembers() { return type => new[] { new InjectionFactory((c, t, n) => { var svc = (ISettings) c.Resolve(t); return svc.LoadSetting(t); }) }; } } 
+9
source

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


All Articles