Hallo zusammen,
ich wende mich mal mit einem etwas außergewöhnlichen Problem an euch. Ich suche eine generelle Vorgehensweise (evtl. auch ein Entwurfsmuster, an das man sich anlehnen könnte), um das im Folgenden beschriebene Problem zu lösen.
Ich entwickle eine Klassenbibliothek, die sich auf eine COM-Bibliothek stützt und deren Funktionalität bündelt und vereinfacht (Facade). Tatsächlich habe ich aber
zwei COM-Bibliotheken, die sich natürlich im Namen (und somit praktisch im Namespace) und geringfügig im Funktionsumfang unterscheiden (grob geschätzt sind 90% gleich).
Ich muss im Idealfall zur Laufzeit entscheiden können, ob ich diese oder jene Bibliothek verwende. Da der Funktionsumfang größtenteils gleich ist, will ich natürlich nicht in jeder einzelnen Methode abfragen, ob ich diese oder jene Bibliothek anspreche. Böses Beispiel:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| using ComA; using ComB;
class MyClass { private ComAObject myComA; private ComBObject myComB;
private string _useWhat;
public MyClass (string useWhat) { this._useWhat = useWhat;
System.Type theType;
theType = System.Type.GetTypeFromProgID("ComA.ComAObject"); this.myComA = (ComAObject) System.Activator.CreateInstance(theType);
theType = System.Type.GetTypeFromProgID("ComB.ComBObject"); this.myComB = (ComBObject) System.Activator.CreateInstance(theType); }
public void Work () { if (this._useWhat == "BibliothekA") { this.myComA.DoSomething(); } else { this.myComB.DoSomething(); } } } |
Was ich eigentlich bräuchte, wäre ein Interface für beide COM-Bibliotheken, auf das ich die meiste Zeit programmieren könnte. Erst wenn eine Methode in einer Bibliothek nicht vorhanden ist oder etwas anders tickt, würde ich tatsächlich unterscheiden.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| using ComA; using ComB;
class MyClass { private IComObject myCom;
private string _useWhat;
public MyClass (string useWhat) { this._useWhat = useWhat;
System.Type theType;
if (useWhat == "BibliothekA") { theType = System.Type.GetTypeFromProgID("ComA.ComAObject"); } else { theType = System.Type.GetTypeFromProgID("ComB.ComBObject"); }
this.myCom = (IComObject) System.Activator.CreateInstance(theType); }
public void Work () { this.myCom.DoSomething(); }
public void WorkDifferent () { if (this._useWhat == "BibliothekA") { (this.myCom as ComAObject).DoSomething(); } else { (this.myCom as ComBObject).DoSomethingDifferent(); } } } |
Dummerweise gibt es dieses Interface nicht und selbst eins zu schreiben übersteigt in Anbetracht des Umfangs der COM-Bibliotheken bei Weitem meine Möglichkeiten.
Eine zugegeben etwas klapprige Idee, die ich schon hatte, war bei Using rumzupfuschen. In etwa so (hab die genaue Syntax nicht im Kopf):
C#-Quelltext
und dann einfach alles auf MyAlias zu schreiben und bei Bedarf an dieser Stelle zentral umzuschalten.
C#-Quelltext
Wäre aber unschön, weil es nicht zur Laufzeit geht, immer noch in zig Dateien geändert werden müsste (oder gibt es sowas wie ein zentrales Using für ein Projekt?) und in sämtlichen Methoden ein extremes Exception-Handling erfordern würde, weil ich ja nie so genau weiß, welche Bibliothek ich gerade vor mir habe. (Ok, ich könnte es anhand einer Testmethode ermitteln, die ich bei der Erstellung aufrufe und an der ich bei Erfolg erkenne, dass es sich um ComA handeln muss und bei Fehler um ComB. Naja.)
Tjo, soweit das Problem. Ich hoffe, ich konnte es halbwegs verständlich rüberbringen. Die Frage ist also: Wie stelle ich das an, damit ich meine Klassenbibliothek nicht zweimal schreiben muss oder das Umschalten von A auf B übermäßig kompliziert und fehleranfällig wird?
Bin natürlich dankbar für jeden Hinweis, der zur Ergreifung äh praktischen Lösung führt.
Moderiert von
Christian S.: Code- durch C#-Tags ersetzt