Unity - ResolveAll по имени с условием - PullRequest
3 голосов
/ 08 мая 2011

Мне было интересно, можно ли разрешить все зависимости в Unity по какому-либо условию имени, для которого они были зарегистрированы.

Например: Восстановление всех интерфейсов, зарегистрированных там, где зарегистрированное имя начинается с «ProcessA».

И если нет способа сделать это, то, возможно, как я могу расширить Unity, чтобы разрешить это.

Ответы [ 2 ]

4 голосов
/ 08 мая 2011

Вы должны иметь возможность использовать Registrations, чтобы сделать это, и я бы порекомендовал метод расширения, а не прямое расширение Unity:

var matches = c.Resolve<IMyService>(name => name.StartsWith("ProcessA"));

Используя этот метод расширения:

public static class MyUnityExtensions
{
    public static IEnumerable<T> Resolve<T>(this IUnityContainer c, Func<string, bool> match)
    {
        var matches = c.Registrations.Where(r => match(r.Name));

        foreach (var registration in matches)
        {
            yield return c.Resolve<T>(registration.Name);
        }
    }

}
1 голос
/ 20 сентября 2013

Просто добавив к ответу Майкла, я расширил его, чтобы позволить вам регистрироваться с теми же именами, но использовать функцию «разрешить все», чтобы разрешить только те, которые зарегистрированы под этим именем.

public struct ScopedName<T>
{
    private const string Separator = "|";

    private readonly string _name;
    private readonly string _registrationName;

    public ScopedName(string name)
        : this()
    {
        _name = name;
        _registrationName = name + Separator + typeof(T).FullName;
    }

    public static implicit operator string(ScopedName<T> scopedName)
    {
        return scopedName._registrationName;
    }

    public bool IsMatach(string other)
    {
        if (string.IsNullOrWhiteSpace(other))
        {
            return false;
        }

        var i = other.IndexOf(Separator, StringComparison.InvariantCulture);
        if (i < 0)
        {
            return false;
        }

        return string.Equals(_name, other.Substring(0, i), StringComparison.InvariantCulture);
    }
}

public static class UnityEx 
{
    public static IUnityContainer RegisterType<TFrom, TTo>(
        this IUnityContainer container,
        ScopedName<TTo> scopedName,
        LifetimeManager lifetimeManager,
        params InjectionMember[] injectionMembers) where TTo : TFrom
    {
        return container.RegisterType(typeof(TFrom), typeof(TTo), scopedName, lifetimeManager, injectionMembers);
    }

    public static IEnumerable<T> ResolveAll<T>(this IUnityContainer container, ScopedName<T> name, params ResolverOverride[] resolverOverrides)
    {
        var matches = container.Registrations.Where(r => name.IsMatach(r.Name));

        foreach (var registration in matches)
        {
            yield return container.Resolve<T>(registration.Name, resolverOverrides);
        }
    }
}

Позволяет регистрировать и разрешать подобные сообщения:

        container.RegisterType<IFoo, Foo1>(new ScopedName<Foo1>("Scope1"), new HierarchicalLifetimeManager());
        container.RegisterType<IFoo, Foo2>(new ScopedName<Foo2>("Scope1"), new HierarchicalLifetimeManager());

        container.RegisterType<IFoo, Foo3>(new ScopedName<Foo3>("Scope2"), new HierarchicalLifetimeManager());
        container.RegisterType<IFoo, Foo4>(new ScopedName<Foo4>("Scope2"), new HierarchicalLifetimeManager());

        var scope1Foos = container.ResolveAll(new ScopedName<IFoo>("Scope1"));
        var scope2Foos = container.ResolveAll(new ScopedName<IFoo>("Scope2"));

scope1Foos будет содержать как Foo1, так и Foo2, scope2Foos будет содержать как Foo3, так и Foo4

...