5

Ich habe eine Baugruppe mit vielen Klassen (300+) mit einer BaseClass und ich möchte eine generische Klasse mit einer Schnittstelle registrieren.Wie kann ich generische Klassen mit einem Namen mit Unity dynamisch registrieren?

Mit Einheit müssen Sie sich registrieren, indem {Name}, wenn Sie ein Array von Objekten der Schnittstelle auflösen möchten. Ich möchte ein Array von Objekten in der MainViewModel automatisch.

Gibt es eine Möglichkeit, dies mit Reflektion zu automatisieren? Irgendwelche Vorschläge?

Beispiel (pseudo):

public class BaseClass 
{ 
    public void doFoo(); 
} 

public ClassNumber001 : BaseClass 
{ 
} 
public ClassNumber002 : BaseClass 
{ 
} 

public interface ISuperman 
{ 
} 

public class Superman : ISuperman where T : BaseClass 
{ 
} 

public MainViewModel(IEnumerable<ISuperman> lotsofSuperman) 
{ 
} 

Arbeitsbeispiel von Hand:

container.RegisterType<ISuperman, Superman <ClassNumber001>>("ClassNumber001"); 
container.RegisterType<ISuperman, Superman <ClassNumber002>>("ClassNumber002"); 
container.RegisterType<IEnumerable<ISuperman>, ISuperman[]>(); 
+0

Ist es obligatorisch, dies durch Reflexion zu tun? Welche Unity-Version verwendest du über 3.x? – gastonmancini

+0

Nein, es ist nicht obligatorisch, ich erwähnte Reflektion, weil ich das vorher benutzt habe. (um die 300 Klassen zu finden) Ich verwende Unity 3.5.1404.0. – Tim

Antwort

0

Es gibt einige Möglichkeiten, wie dies getan werden kann. Einer besteht darin, XML zu verwenden, wo der Typ definiert ist, sagen wir MyClass und IMyClass, und zur Laufzeit löst er basierend auf den verfügbaren Assemblys auf. Aber ein besserer Ansatz wäre meiner Meinung nach, ein Projekt zu erstellen, an das Sie die Verantwortung für das Laden der Abhängigkeiten delegieren können.

Können sagen, Sie eine Klasse wie so erstellen:

 public class MyClass : IMyClass 
    { 
     private readonly IUnityContainer _container; 

     #ctor 
     // initialie the container through the constructor 

     public void DoWork<Interface, Class>() where Class: Interface 
     { 
      _container.RegisterType<Interface, Class>(
      //TODO: You can setup the container lifecycle which can be transient 
      // or singleton or custom based on your project requirement 
      ) 
     } 
    } 

Wer nun braucht, um sich registrieren können diese Schnittstelle IMyClass nennen sich in dem Behälter und die Abhängigkeit registrieren lassen können injiziert werden, je nachdem, welche Klasse durchführen muss, dass Aufgabe.

1

Ja, Sie müssen Reflektion zu einfach erstellen Sie alle Zuordnungen, die Sie möchten. Da Sie Unity 3 verwenden, können Sie die Registration by Convention nutzen, um beim Registrieren der Klassen Hilfe (mit dem schwereren Heben) zu leisten.

ich Ihre Pseudo-Code genommen haben und es in echten Code übersetzt:

public abstract class BaseClass 
{ 
    public abstract void DoFoo(); 
} 

public class ClassNumber001 : BaseClass 
{ 
    public override void DoFoo() 
    { 
     Console.WriteLine("001 Foo"); 
    } 
} 

public class ClassNumber002 : BaseClass 
{ 
    public override void DoFoo() 
    { 
     Console.WriteLine("002 Foo"); 
    } 
} 

public interface ISuperman 
{ 
    void Do(); 
} 

public class Superman<T> : ISuperman where T : BaseClass 
{ 
    private T baseClass; 

    public Superman(T baseClass) 
    { 
     this.baseClass = baseClass; 
    } 

    public void Do() 
    { 
     this.baseClass.DoFoo(); 
    } 
} 

public class MainViewModel 
{ 
    public MainViewModel(IEnumerable<ISuperman> lotsofSuperman) 
    { 
     foreach(ISuperman superman in lotsofSuperman) 
     { 
      superman.Do(); 
     } 
    } 
} 

Dann Registrierung verwenden vereinbarungsgemäß alle Generika zu registrieren:

IUnityContainer container = new UnityContainer(); 

container.RegisterTypes(
    AllClasses.FromAssembliesInBasePath().Where(t => typeof(BaseClass).IsAssignableFrom(t)) 
     .Select(t => typeof(Superman<>).MakeGenericType(t)), 
    t => new Type[] { typeof(ISuperman) }, 
    t => t.GetGenericArguments().First().Name, 
    WithLifetime.Transient); 

container.RegisterType<IEnumerable<ISuperman>, ISuperman[]>(); 

container.Resolve<MainViewModel>(); 

In dem obigen Code, den wir alle bekommen Klassen, die von BaseClass erben und dann einen Typ Superman<> konstruieren und den ISuperman unter Verwendung des Namens BaseClass zuordnen.Der RegisterTypes Aufruf für jede Baseclass zu nennen RegisterType gleichwertig sein wird:

container.RegisterType<ISuperman, Superman<ClassNumber001>("ClassNumber001"); 
container.RegisterType<ISuperman, Superman<ClassNumber002>("ClassNumber002"); 

Dann, wenn MainViewModel wird es alle ISuperman Instanzen iteriert aufgelöst und ruft eine Methode, die ausdruckt:

001 Foo
002 foo

zeigen, dass wir 2 ISuperman Fällen injiziert: Superman<ClassNumber001> und 01.234..

Wenn Sie spezifische Registrierungen für die BaseClasses benötigen (z. B. Nicht-Standard-Lifetime Manager), können Sie die Registrierung auch per Konvention verwenden, um diese ebenfalls zu registrieren).