![]() |
AW: Interface richtig umgesetzt?
Zitat:
Danke |
AW: Interface richtig umgesetzt?
Zitat:
Diese eine Instanz wird dann in einer Factory Methode verwendet die eine Connection liefert:
Delphi-Quellcode:
Und dann kann im Programm an beliebigen Stellen - die natürlich auf die MyApp Instanz zugreifen können - eine Connection erzeugt und geöffnet werden, zum Beispiel in einem Thread.
function TMyApp.CreateConnection: IConnection;
begin Result := MyMSMQBrokerClient.CreateConnection; end;
Delphi-Quellcode:
(Exceptionbehandlung für Verbindungsverlust etc. mal weggelassen).
procedure TMyDoWorkThread.Execute;
var Conn: IConnection; Msg: string; begin Conn := MyApp.CreateConnection; Conn.Start; while not Terminated do begin Msg := Conn.Receive(1000); // mach etwas mit der erhaltenen Nachricht... end; Conn.Stop; end; |
AW: Interface richtig umgesetzt?
Ok, verstanden.
Hab gerade etwas rumprobiert und gesehen, dass in deinem Beispiel MyMSMQBrokerClient.CreateConnection einen Zeiger auf IConnection zurückgibt (denke ich). Doch ich bekomme den Inhalt für "CreateConnection" nicht hin. Was muss ich konrekt reinschreiben, um eine IConnection zurückzubekommen? Danke für eure Geduld ;) EDIT Ich glaube, ich habe es! Interfaces - Die Klasse TMyMQ wird gelöscht, da überflüssig (wie vermutet)
Delphi-Quellcode:
und hier kommt in der programmweiten Verwendung der Knackpunkt. Es wird nicht TMy_MQ erstellt, sondern direkt eine Variable IMy_MQ, welche dann via TMy_MSMQ.Create mit dem Interfacezeiger gefüllt wird:
IMy_MQ = interface
... ... end; TMy_MSMQ = class(TInterfacedObject, IMy_MQ) ... ... end;
Delphi-Quellcode:
Richtig? Es funktioniert jedenfalls. Aber hatte meine erste Version ja auch ;)
procedure TForm1.Button2Click(Sender: TObject);
var mq: IMy_MQ; begin mq:=TMy_MSMQ.Create; mq.SendMessage; end; |
AW: Interface richtig umgesetzt?
Sieht sauberer aus als am Anfang, es ist aber auch viel weniger Code :P
|
AW: Interface richtig umgesetzt?
Das freut mich. Nun muss es auch nur richtig sein ;)
Es ergibt sich aber jetzt dadurch das Problem, dass ich dennoch viel eingeschränkter hinsichtlich Parameter bin. Angenommen, mein Interface hat die Methode "Open". Mit dieser möchte ich entweder bei MS die Queue öffnen, oder eben bei ActiveMQ. Nun fordert MSMQ bei dessen Open-Methode Parameter A, B, C, ActiveMQ fordert Parameter 1, 2. Da ich nun durch
Delphi-Quellcode:
nur Zugriff auf die Interface-Methoden habe, bleiben die Methoden/Felder von TMy_MSMQ verborgen. Nun stehe ich also vor dem Problem, dass ich nicht weiß, wie ich innerhalb meiner Open-Methode auf die verschiedenen Erfordernisse der jeweiligen Message-Queue Objekte eingehen kann.
var
mq: IMy_MQ; begin mq:=TMy_MSMQ.Create; EDIT: Ich könnte natürlich auch einen Cast nach TMy_MSMQ durchführen, um auf die Methoden/Felder dieser Klasse zuzugreifen. So könnte ich Parameter setzen, die dann wieder in "Open" ausgelesen werden. |
AW: Interface richtig umgesetzt?
Gut, wenn sich die Parameter so unterscheiden, dann hast Du zusätzlich zu der "allgemeinen" Schnittstelle auch noch speziellere Schnittstellen, mit entsprechenden Methoden.
Dann kannst Du das aber nicht sauber mit einem allgemeinen Typ abbilden (auch mit Klassen nicht). Du musst quasi schon VOR dem Verwenden wissen, ob es sich um eine MQ mit 2 oder mit 3 Parametern handelt. Die Optionen die ich hier sehe sind also: - Du versucht eine allgemeines "Open" zu definieren und die eine Klasse verwendet alle 3 Parameter, die anderen nur 2 (das ist aber nicht gerade die feine englische Art) - zwei separate "Basis" Interfaces, einmal für das Open mit 3 Parametern, einmal mit 2 Parametern - ein Basis-Interface mit zwei Spezialisierungen (abgeleitete Interfaces, jeweils mit der eigenen Open-Definition) Allerdings kenne ich auch hier nicht Deinen kompletten Anwendungsfall. Des Weiteren stell ich mal die Frage: gibt es nicht bereits vorhandene Implementierungen im Netz ? |
AW: Interface richtig umgesetzt?
Vielen Dank für die Antworten.
Ausgangspunkt war folgender: Ich wusste nicht, welche MessageQueue-Lösung ich final im Produkt verwenden möchte. Für den Anfang reicht MSMQ. Vielleicht kommt irgendwann mal ein MAC-Client o.ä. dazu. Dann hab ich mit MSMQ schlechte Karten und müsste auf ActiveMQ (oder einen anderen) umsteigen. Daher riet mir Sir Rufo, ein Interface zu implementieren und später beim Umstieg nur einen winzigen Teil im Programm ändern müsste. Daher ein Interface mit z.B. "Open" (welches die MessageQueue öffnet). MSMQ verlangt zwei Parameter. ActiveMQ mit Sicherheit ganz andere. Und darauf weiß ich gerade nicht zu reagieren, außer einen Typecast zum TMy_MSMQ-Objekt oder einem Array im Interface namens "Params", die vor dem Open (oder anderen Methoden) entsprechend gefüllt und in der Methode ausgelesen und wieder gelert, quasi als Container. Wenn wir die Interface-Geschichte mal außen vor lassen: Mit der MSMQ komme ich nun in den Grundzügen klar, kann erstellen, lesen, schreiben etc. |
AW: Interface richtig umgesetzt?
Also wenn ich einen Brief versenden will, dann muss ich trotzdem nicht das Postamt öffnen, oder den Briefkasten aufschließen. Ich gehe einfach zu meinem Interface
Delphi-Quellcode:
und sende den Brief ab mit
IBriefPost
Delphi-Quellcode:
. Soll sich das Interface doch selber darum kümmern. ;)
IBriefPost.Sende( Brief);
|
AW: Interface richtig umgesetzt?
Ich verstehe, was du damit sagen willst. Bleiben wir dabei: Es gibt die Post, TransoFlex und UPS. Bei allen kann ich noch Post fragen. Dafür habe ich IMessages.GetMessage.
Nun kann ich bei der Post auswählen, ob nur das Vorliegen neuer Post erfragt werden soll und wer das machen darf (Open MQ_RECEIVE_ACCESS, MQ_DENY_NONE), erfragen und gleich mitnehmen <bei Post löschen> aber nur spezielle Leute das machen dürfen (Open MQ_PEEK_ACCESS, MQ_DENY_RECEIVE_SHARE) etc. Bei TransoFlex kann ich genau das gleiche machen, nur nicht festlegen, wer diese Aktionen durchführen darf. UPS will garnicht genau wissen, was ich vorhabe, sondern ich kann mich selbst dort bedienen. Wie soll ich darauf mit IMessage.GetMessage reagieren? Ich habe als Zwischenlösung (nur damit ich weiter testen kann) ein Array mit Parametern angelegt:
Delphi-Quellcode:
Funktioniert, ist aber nicht optimal...
procedure TMy_MSMQ.SetParam(Value: string);
begin SetLength(fParams, Succ(Length(fParams))); fParams[High(fParams)]:=Value; end; ... procedure TMy_MSMQ.QueueOpen begin fQueue:=fQueueInfo.Open(StrToInt(fParams[0]), StrToInt(fParams[1])); //MQ_SEND_ACCESS / MQ_RECEIVE_ACCESS etc. end; procedure TForm1.Button2Click(Sender: TObject); var mq: IMy_MQ; begin mq:=TMy_MSMQ.Create; //Verbinden mq.SetParam(IntToStr(MQ_RECEIVE_ACCESS)); mq.SetParam(IntToStr(MQ_DENY_NONE)); if (mq.QueueOpen('DIRECT=OS:.\Private$\Test')) then ShowMessage('Queue opened'); end; |
AW: Interface richtig umgesetzt?
Zitat:
Zitat:
Das ist insofern unschön, da Du einen undefiniertem Wert übergibst den Du innerhalb der Open-Implementierung ja wieder auswerten musst- man sieht innerhalb der Open-Implementierung also gar nicht auf den ersten Blick was gemeint ist. Alternative mit Parametern zu Deinem Beispiel: Sofern Du dabei bleiben möchtest, ein MQ-Interface bereitzustellen mit einem allgemeingültigen Open-Aufruf, dann solltest Du die Parameter sogt wie möglich typisieren. Du hast ja überall definierte Zustände, das bedeutet alle "Rechte" kannst Du als Enums darstellen (wie Du diese letztendlich gestaltest überlass ich mal Dir), die man dann entsprechend auch einfach und leserlich auswerten kann. Wenn möglich könntest Du sogar ein großes Enum deklarieren und in der Open-Methode einfach ein Enum-Set verlangen, z.B:
Delphi-Quellcode:
Jede Implementierung entscheidet dann selbst, ob und wie die übergebenen Parameter verwertet werden. Der Vorteil ist, Du musst beim austauschen der MQ-Implementierung nicht den Open-Aufruf anpassen und siehst gleich am Namen des Enums um was für ein Recht es sich handelt und kannst entsprechend einfach darauf prüfen und es auswerten. Nachteil ist weiterhin , dass man hier keine Rückmeldung erhält, sofern gesetzte (Rechte)Parameter ignoriert werden.
TMQSetupType = (mqsReceiveAccess, mqsDenyNone, mqsPeekAccess, mqsDenyReceiveShare);
TMQSetupTypes = set of TMQSetupType; IMyMQ= interface ... procedure Open(const ASetup: TMQSetupTypes); end; ..... procedure TMy_MSMQ.QueueOpen begin fQueue:=fQueueInfo.Open([mqsSendAccess, mqsReceiveAccess]); end; Alternativen: Du solltest Dir einfach mal die MQ-Implementierungen anderer Sprachen anschauen und herausfinden wie das dort gelöst wurde (der Anwendungsfall sollte ja exakt der gleiche sein) - vielleicht findet sich da ja eine elegante Lösung, oder jemand anderem im Forum fällt bis dahin was schickes ein. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz