2016-07-20 17 views
1

Ist es möglich, dieselbe Schnittstelle zweimal zu registrieren, wobei die erste zu einer Standardimplementierung aufgelöst wird und die zweite einen Namen hat und in einen anderen Typ aufgelöst wird.Kann der Einheits-Container den Standardtyp auflösen, wenn der Name nicht gefunden wird?

Beispiel:

container.RegisterType(typeof(IMyInterface), typeof(MyDefaultImplementation)); 
container.RegisterType(typeof(IMyInterface), typeof(MySecondImplementation),"Second Implementations name"); 

So

Resolve<IMyInterface>("non existing name") 

Sollte MyDefaultImplementation lösen.

public class DefaultRegistrationFallbackConfiguration : UnityContainerExtension 
{ 
    protected override void Initialize() 
    { 
     this.Context.Registering += this.AppendRemapPolicy; 
    } 

    public override void Remove() 
    { 
     this.Context.Registering -= this.AppendRemapPolicy; 
    } 

    private void AppendRemapPolicy(object sender, RegisterEventArgs e) 
    { 
     if (e.Name != null) 
      return; 

     if (e.TypeFrom != null && e.TypeTo != null) 
      this.Context.Policies.SetDefault<IBuildKeyMappingPolicy>(new MapBuildKeyToDefaultPolicy(e.TypeFrom, e.TypeTo)); 

     if (e.LifetimeManager == null) 
      return; 

     throw new NotImplementedException("TODO: lifetime management"); 
    } 
} 

Erstellen Sie Ihre eigenen IBuildKeyMappingPolicy:

public class MapBuildKeyToDefaultPolicy : IBuildKeyMappingPolicy 
{ 
    private readonly Type _typeFrom; 
    private readonly Type _typeTo; 

    public MapBuildKeyToDefaultPolicy(Type typeFrom, Type typeTo) 
    { 
     this._typeFrom = typeFrom; 
     this._typeTo = typeTo; 
    } 

    public NamedTypeBuildKey Map(NamedTypeBuildKey buildKey, IBuilderContext context) 
    { 
     if (buildKey.Type == this._typeFrom) 
      return new NamedTypeBuildKey(this._typeTo); 

     throw new InvalidOperationException(); 
    } 
} 

Test-Klassen, die Sie besitzen Konfiguration, fügen Sie es als Erweiterung

+0

Ja, Sie Ihre benutzerdefinierte erstellen 'BuilderStrategy'. Sie können sich die akzeptierte Antwort zu dieser Frage ansehen. Aber Sie sollten vielleicht noch einmal überdenken, ob es tatsächlich das ist, was Sie tun möchten ... http://stackoverflow.com/questions/1380375/custom-object-factory-extension-for-unity – smoksnes

Antwort

2

Ich bin nicht so vertraut mit der Einheit, aber Sie Katze beginnen mit der Erstellung:

public interface IFoo 
{ 
    void Bar(); 
} 

public class FooNamed : IFoo 
{ 
    public void Bar() 
    { 
     Console.WriteLine("named one"); 
    } 
} 

public class FooDefault : IFoo 
{ 
    public void Bar() 
    { 
     Console.WriteLine("default one"); 
    } 
} 

Test:

public static class Program 
{ 
    static void Main(string[] args) 
    { 
     var container = new UnityContainer(); 

     // register extension before use container! 
     container.AddExtension(new DefaultRegistrationFallbackConfiguration()); 

     container.RegisterType(typeof(IFoo), typeof(FooDefault)); 
     container.RegisterType(typeof(IFoo), typeof(FooNamed), "named"); 

     container.Resolve<IFoo>()   .Bar(); // default one 
     container.Resolve<IFoo>("named") .Bar(); // named one 
     container.Resolve<IFoo>("unknown").Bar(); // default one 
    } 
} 

Ausgang:

Standard ein
namens ein
Standard ein

3

Wenn Sie mit der Verwendung des Behälters OK sind Sie eine Erweiterungsmethode tun:

public static class UnityExtensions 
{ 
    public static T TryResolve<T>(this IUnityContainer container, string name) 
    { 
     if (container.IsRegistered<T>(name)) 
      return container.Resolve<T>(name); 

     return container.Resolve<T>(); 
    } 
} 

Und verwenden Sie es wie:

container.RegisterType<IMyInterface, Foo>(); 
container.RegisterType<IMyInterface, Bar>("bar"); 

var foo = container.TryResolve<IMyInterface>("non-existing"); 
// foo will be Foo 
var bar = container.TryResolve<IMyInterface>("bar"); 
// bar will be Bar. 

public interface IMyInterface { } 
public class Foo : IMyInterface { } 
public class Bar : IMyInterface { } 

Der Nachteil ist, dass Sie müssen wissen, wann die Erweiterung verwenden und wann nicht ... Ansonsten können Sie Ihre eigenen BuilderStrategy zu bauen.

Stark influensed von:

Unity - loadConfiguration, how to resolve only those configured

Is there TryResolve in Unity?