如何设置Unity注册约定?

时间:2014-12-09 04:17:03

标签: c# dependency-injection unity-container

使用结构图,您可以注册一个约定,它不仅可以调整类型,还可以在创建对象时进行干预。我怎么能用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);
            });
        }
    }
}

1 个答案:

答案 0 :(得分:14)

您可以结合使用Unity Registration by ConventionInjectionFactory来完成此操作。我看到了三种常见的实施方案,但我确信还有更多......


选项1

如果条件内联在lambda表达式中,则一次注册所有类型。如果您注册许多具有许多自定义注册的类型,这不能很好地扩展...

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];
    });

选项2

仅注册ISettings类型并提供一些不错的帮助方法。您需要多次调用container.RegisterTypes,但它更具可读性......

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);
    }
}

选项3

或者你可以创建一个派生自RegistrationConvention的类,让该类做出所有的注册决定......

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);
            })
        };
    }
}