| 

.NET C# Java Javascript Exception

2
Hallo zusammen,
ich habe auf meine Webservice-Infrastruktur einen zusätzlichen Layer gebastelt, um die Webdienste konform zu einem Industriestandard zu machen. Ich bin gerade dabei, diese Schicht zu überarbeiten. U.a. gibt es eine Execute-Methode, welche abhängig von einem Parameter einen bestimmten Webdienst ausführt und das Ergebnis an einen Client zurückliefert. Bisher mache ich das über einen Switch/case, also ungefähr so:

C#-Code:
public void Execute( ref WPSProcess process )
{
switch( process.ProcessBriefType.Identifier.Text )
{
case "Gelaendeinfo":
ExecuteGelaendeinfo( ref process );
break;
case "GW-Basis":
ExecuteGWBasis( ref process );
break;
case "Gelaendeprofil":
ExecuteGelaendeprofil( ref process, false );
break;
//...
}
}


// Anschließend folgt die Implementierung der einzelnen Execute-Methoden
private void ExecuteGelaendeinfo(ref WPSProcess process)
{
// hier wird der Webdienst aufgerufen...
}


Das funktioniert zwar, ist aber sicher nicht die eleganteste Vorgehensweise. Kennt jemand ein gutes Muster, wie man so etwas implementieren kann? Da immer wieder neue Webdienste hinzukommen, spielt natürlich der Aspekt der flexiblen Erweiterung eine große Rolle. Ich lese gerade ein Buch zum Thema Entwurfsmuster und bin gerade beim Factory-Pattern. Könnte mir vorstellen, dass man dieses Muster hierfür verwenden kann. Aber ich bin noch nicht durch mit dem Buch, gibt es evtl bessere Muster oder Konzepte? Wäre dankbar für einen Tipp!

Viele Grüße
shabi79
News:
07.03.2011
shabi79 111 1
Gibt es einen Grund warum Du nicht die einzelnen Methoden als Service-Methoden bereitstellst? Die kann man auch beliebig erweitern.
Florian Mätschke 07.03.2011
grob zusammengefasst ist das so: Wir haben Geofunktionen, welche wir bisher über eine XML-Webservice-Schicht bereitgestellt haben. Nun habe ich eine weitere Schicht erstellt, um diese Dienste einem neuen Geo-Standard konform zu machen. Die Methoden oben werden nur intern in dieser Schnittstelle genutzt um die bestehenden XML Webservices aufzufrufen und sind kein Endpunkt nach außen. Ich frage mich nur, ob es nicht eine generischere Variante wie das switch/case gibt. Vielleicht schaue ich mir noch mal das Strategy-Muster an, wie von Matthias vorgeschlagen.
shabi79 07.03.2011
3 Antworten
0
So ganz überblicke ich nicht, was Du da genau vorhast. Aber ein möglicher Kandidat, um switch-case-Verzweigungen loszuwerden, ist das Strategie-Muster.
07.03.2011
Matthias Hlawatsch 8,4k 2 8
0
Hallo,

ich habe es mal mit einer Art "Hashed Adapter Objects" (Pattern) versucht:

Aufbau:

  • Interface
  • Jede Methode aus dem switch Statement wird in einem Objekt bereitgestellt, das das Interface implementiert
  • Factory, die ein Dictionary der Objekte hält
  • Die Factory instanziert beim Aufruf das entsprechende Objekt, und führt die Interface Method aus (Execute = Methode aus dem switch)

Nutzen: Für neue Services muss nur ein neuer Typ angelegt werden, der von IExecute ableitet, sowie der Konstruktor der Factory Klasse um einen Eintrag ergänzt werden.

Erstmal benötigt es ein Interface:

interface IExecute
{
void Execute(WPSProcess process);
}

Danach legst du für jede Methode eine Klasse an, die dieses Interface implementiert. Die Execute Methode entspricht jener aus deinem switch Statement:

class GelaendeInfo : IExecute
{
#region IExecute Members

public void Execute(WPSProcess process)
{
//...
}

#endregion
}

class GWBasis : IExecute
{
#region IExecute Members

public void Execute(WPSProcess process)
{
//...
}

#endregion
}

class Gelaendeprofil : IExecute
{
#region IExecute Members

public void Execute(WPSProcess process)
{
//...
}

#endregion
}

Und schließlich der Kern, die Factory, die jedes Object in einem Dictionary hält, das nach Bedarf instanziert und die Execute Methode ausgeführt wird.

class Factory
{
private static Dictionary<string, Type> actions = new Dictionary<string, Type>();
private static Factory _instance = new Factory();

public static void Execute(WPSProcess process)
{
string processInfoText = process.ProcessBriefType.Identifier.Text;
(actions[processInfoText].GetConstructor(Type.EmptyTypes).Invoke(null) as IExecute).Execute(process);
}

private Factory()
{
actions.Add("GelaendeInfo", typeof(GelaendeInfo));
actions.Add("GWBasis", typeof(GWBasis));
actions.Add("Gelaendeprofil", typeof(Gelaendeprofil));
}
}


Anstelle des switch benötigst du dann nur noch:

class Service
{
public void Execute(ref WPSProcess process)
{
Factory.Execute(process);
}
}


Obige Version verwendet Reflection, um den Konstruktor aufzurufen, eine andere Variante wäre:

class Factory
{
private static Dictionary<string, IExecute> actions = new Dictionary<string, IExecute>();
private static Factory _instance = new Factory();

public static IExecute GetInstance(string processInfoText)
{
return actions[processInfoText];
}

private Factory()
{
actions.Add("GelaendeInfo", new GelaendeInfo());
actions.Add("GWBasis", new GWBasis());
actions.Add("Gelaendeprofil", new Gelaendeprofil());
}
}

class Service
{
public void Execute(ref WPSProcess process)
{
Factory.GetInstance(process.ProcessBriefType.Identifier.Text).Execute(process);
}
}

Weitere Varianten sind denkbar, eventuell macht auch ein Implementieren von IDisposable auf den Objekten Sinn, andererseits wenn sie keine Daten halten kann man die Execute Methode auch ohne Interface als static implementieren und diese mittels Reflection aufrufen...

hth

maria
07.03.2011
Maria Simlinger 864 8
0
Mir ist eine ultimativ kurze Version eingefallen:

class Service
{
private Dictionary<string, Action<WPSProcess>> _actions = new Dictionary<string, Action<WPSProcess>>();

public Service()
{
_actions.Add("GelaendeInfo", this.GelaendeInfo);
_actions.Add("GW-Basis", this.GWBasis);
_actions.Add("Gelaendeprofil", this.Gelaendeprofil);
}

void GelaendeInfo(WPSProcess process)
{
}
void GWBasis(WPSProcess process)
{
}
void Gelaendeprofil(WPSProcess process)
{
}

public void Execute(WPSProcess process)
{
_actions[process.ProcessBriefType.Identifier.Text](process);
}
}


Der Aufruf erfolgt dann mittels:

new Service().Execute(process)


Ich schätze das trifft besser ins Ziel, als meine erste Variante :)
08.03.2011
Maria Simlinger 864 8
Hallo Maria,
guter Ansatz. Ich denke Deine Vorgehensweise über den Action-Delegate ist ein guter Ansatz. Bin gerade dabei, das umzusetzen. Vielen Dank für Deine Ideen!
shabi79 09.03.2011

Stelle deine .net-Frage jetzt!