| 

.NET C# Java Javascript Exception

2
Hallo,
ich versuche IoC mit AutoFac zu verstehen und scheitere im Augenblick an folgendem Problem:

Ich habe mehrere Klassen, die alle das gleiche Interface implementieren. Welche Klasse ausgewählt werden soll, wird durch ein Enum bestimmt. Ich habe ein Factory Klasse, welche die Klasse entsprechend des übergebenen Enums zurück liefert. Es gibt eine weitere Klasse, welche eine der voranstehenden Klassen nutzt und per Konstruktor-Injektion diese injiziert bekommt.

Ich möchte nun erreichen, dass AutoFac mir die Hauptklasse mit der, entsprechend eines Enumwertes, korrekten injizierten Klasse liefert.

Alles was ich bis jetzt versucht habe führt zu einer Fehlermeldung, dass die injizierte Klasse nicht instantiiert werden kann.

enum Kennzeichen { TypA, TypB }
interface IX { }
class A : IX { }
class B : IX { }
class HauptKlasse
{
private IX _ix;

public HauptKlasse (IX ix)
{
_ix = ix;
}
}

class Factory
{
public IX Get (Kennzeichen k)
{
switch (k)
{
case Kennzeichen.TypA:
return new A ();
case Kennzeichen.TypB:
return new B ();
default:
throw new ArgumentException ("k");
}
}
}

void main ()
{
var builder = new ContainerBuilder ();

?????
var container = builder.Build();

A a = container.??????
}


Ich wäre für jede Hilfe dankbar!
28.02.2013
mph 227 1 6
Kannst Du erklären, was Dein Ziel bei diesem Vorgehen ist und warum Du diesen Ansatz verfolgst? Vlt. gibt es andere Lösungsmöglichkeiten. Hier noch ein paar Links:

https://code.google.com/p/autofac/wiki/ComponentCreation#Selection_of_an_Implementer_based_on_a_Parameter_Value

https://code.google.com/p/autofac/wiki/DelegateFactories
ffordermaier 01.03.2013
@Ffordermaier
Vielen Dank für die Links!
mph 01.03.2013
1 Antwort
1
Hallo,

persönlich finde ich das nicht so doll.
Hier aber ein anderer Vorschlag. Alle Implementierungen des Interfaces werden als Kontruktorparameter mit in die Hauptklasse injiziert.

public class Hauptklasse : IHauptklasse
{
private readonly IFoo[] _foos;

public Hauptklasse(IFoo[] foos)
{
_foos = foos;
}

public void DoSomething(Kennzeichen kennzeichen)
{
var foo = _foos
.Where(x => x.HasKennzeichen(kennzeichen) == true)
.FirstOrDefault();

if (foo != null)
{
string wasAuchImmer = foo.GetWasAuchImmer();
}
}
}

public interface IFoo
{
bool HasKennzeichen(Kennzeichen kennzeichen);

string GetWasAuchImmer();
}

public class AFoo : IFoo
{
public bool HasKennzeichen(Kennzeichen kennzeichen)
{
return kennzeichen == Kennzeichen.A;
}

public string GetWasAuchImmer()
{
return "A";
}
}

public class BFoo : IFoo
{
public bool HasKennzeichen(Kennzeichen kennzeichen)
{
return kennzeichen == Kennzeichen.B;
}

public string GetWasAuchImmer()
{
return "B";
}
}

public class CFoo : IFoo
{
public bool HasKennzeichen(Kennzeichen kennzeichen)
{
return kennzeichen == Kennzeichen.C;
}

public string GetWasAuchImmer()
{
return "C";
}
}

public enum Kennzeichen
{
A,
B,
C
}

ggf. kann die ganze Logik aus DoSomething() auch nochmals in einer separaten Klasse gekapselt werden.

Die Registrierung:

var containerBuilder = new ContainerBuilder();

containerBuilder.RegisterType<AFoo>().Keyed<IFoo>("A").AsImplementedInterfaces();
containerBuilder.RegisterType<BFoo>().Keyed<IFoo>("B").AsImplementedInterfaces();
containerBuilder.RegisterType<CFoo>().Keyed<IFoo>("C").AsImplementedInterfaces();

// mit Interface
//containerBuilder.RegisterType<Hauptklasse>().As<IHauptklasse>();

// ohne Interface
containerBuilder.Register(context =>
{
var foos = context.Resolve<IEnumerable<IFoo>>();
return new Hauptklasse(foos.ToArray());
});

var container = containerBuilder.Build();

// mit Interface
//var instance = container.Resolve<IHauptklasse>();

// ohne Interface
var instance = container.Resolve<Hauptklasse>();


Wäre halt ein Vorschlag :-)
28.02.2013
lbm1305 849 1 8
lbm1305 849 1 8
@ibm1305:
Danke für die tolle Lösung! Werde ich so versuchen!
mph 01.03.2013
L nicht i ;-)
Vorteil der Implementierung: wenn Du ein weiteres Kennzeichen einfügst, erstellst einfach eine neue Implementierung von IFoo. Somit muss die eigentliche Logik nicht verändert werden. Mögliche Anpassungen an Tests wären immens, vorallem dann, wenn man dann doch wieder feststellt, das man die neue Klasse gar nicht braucht.
lbm1305 01.03.2013

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH