How to setup a Unity Registration Convention?

前端 未结 1 1509
一个人的身影
一个人的身影 2021-02-20 17:54

With structure map, you can register a convention that lets you not just tweak the type, but also intervene during object creation. How can I do this with Unity.



        
1条回答
  •  梦如初夏
    2021-02-20 18:31

    You can do this with a combination of Unity's Registration by Convention and an InjectionFactory. I see three common options for implementation, though I'm sure there are more...


    Option 1

    Register all type at once with if conditions inline in a lambda expression. Though this does not scale well if you are registering many types with many custom 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 the ISettings types and supply some nice helper methods. You will need to call container.RegisterTypes multiple 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 IsSetting(this IEnumerable types)
        {
            return types.Where(type => !type.IsAbstract && 
                                       typeof (ISettings).IsAssignableFrom(type));
        }
    
        public static IEnumerable 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 could create a class derived from RegistrationConvention and let that class make all of the registration decisions...

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

    0 讨论(0)
提交回复
热议问题