2011-05-08 41 views
3

我想知道是否有可能在註冊名稱的某個條件下解決Unity中的所有依賴項。Unity - 通過名稱條件解析所有條件

例如: 重新註冊註冊名稱的所有接口以「ProcessA」開頭。

如果沒有辦法做到這一點,那麼或許我該如何擴展Unity來允許這樣做。

+0

調用到容器直接通常被認爲是一種抗-模式。如果您能夠爲您的問題提供更多背景信息(您想解決什麼問題),或許我們可以爲您提供一些關於如何改進設計的提示。 – Steven 2011-05-08 19:11:23

回答

4

你應該能夠使用Registrations做到這一點,我會建議一個擴展方法,而不是直接擴展統一:

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

只是增加了邁克爾的答案,我擴展了這一點,以允許您使用相同的名稱進行註冊,但使用全部解決方法僅解決針對該名稱註冊的那些名稱。

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