Announcement

Collapse
No announcement yet.

Name eines Objects als Parameter übergeben

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Name eines Objects als Parameter übergeben

    <pre>
    Hallo,
    ich möchte ein Objekt Instanzieren, dessen Name ich als String-Parameter
    übergebe. Der TYPE des Object ist bis dahin noch unbekannt. Dieser soll
    mittels des übergebenen String ermittelt werden.
    Der Type ist in irgend einer Unit des Projekts angelegt und die Unit
    ist unter <b>uses</b> eingebunden.
    Wie geht so was in Delphi.

    Helmut
    </pre>

  • #2
    <pre>

    var
    Class: TPersistentClass;
    Persistent: TPersistent;
    begin
    RegisterClass(TBitmap);
    Class := GetClass('TBitmap');
    if Class <> nil then
    Persistent := Class.Create;
    end;

    </pre&gt

    Comment


    • #3
      <pre>
      Hallo Hagen,
      zu nächst mal vielen Dank für die schnelle Reaktion.
      In meiner Anwendung sind unterschiedliche Threads zu starten.
      Jeder Thread ist eine Klasse vom Typ Thread dieser ist leider von
      TObject abgeleitet. Über ein Interface übergebe ich den Namen des zu startenden Thread als String. Alle Threads haben einen geänderten Constructor, welchem Parameter übergeben werden.

      Gibt es dafür auch eine Lösung?

      Helmut
      </pre&gt

      Comment


      • #4
        Nein, nicht in ObjectPascal. Das was Du willst geht sogar in Interpretierenden Sprachen sehr schlecht.
        Man könnte die Constructoren vereinheitlichen, alle Thread müssen von
        ein und der selben KLassen abgeleitet sein, und in dieser Klasse werden die Interfaces zur individuellen Initialisierung vorgegeben.
        Dann müsste jeder abgeleitete Thread diese Interfacebeschreibungen überschreiben, und deine allgemeine Thread-Erzeugung Funktion die Informationen benutzen um eine korrekte Parameterübergabe zu bekommen.<br>

        Allerdings wäre das dann am Sinn von OOP weit vorbei. Am besten ist es mal wenn du beschreibst in welchem Szenario du dies benötigst. Vielleicht lässt sich das Problem ganz anders lösen.


        Gruß Hage

        Comment


        • #5
          <pre>
          Hallo Hagen,
          zur Anwendung:
          Eine Client / Server-Anwendung
          Im Server gibt es etwar 20 Klassen, die von Thread abgeleitet sind.
          Darüber haben alle Klassen eine gemeinsame Klasse in der der Construktor angelegt ist. Also der Aufruf ist immer der selbe.
          Darüber liegt dann die Klasse, in der die spezifischen funktionen liegen. Diese haben alle andere Namen und mit dem Name wird die Klasse dann aufgerufen. Dieser Name wird vom Client dem Server übergeben.
          Nun wird dort der String abgefragt und mit if-Bedingungen die zu startende Klasse aufgerufen.
          Ich versuche mal zu beschreiben
          TObjekt-TThread-ClassMitCreate-Txyz;
          TObjekt-TThread-ClassMitCreate-Tzyx;
          ... usw.

          procedure(Modul: String; P1, P2, P3: Integer);
          begin
          if Modul = 'xyz' then
          xyz := Txyz.create(P1,P2,P3);
          .
          .
          .
          if Modul = 'zyx' then
          zyx := Tzyx.create(P1,P2,P3);
          end;
          In der Anwendung sieht das natürlich wesendlich unübersichtlicher aus.
          Ich dachte mir, man könne einen Variant benutzen, und dem an Hand des
          Namen den Typ übergeben und diesen Starten.

          Helmu

          Comment


          • #6
            Naja, falls alle diese Thread Object den gleichen constructor habe geht das doch:

            <pre>

            type
            TBaseThreadClass = class of TBaseThread;
            TBaseThread = class(TThread)
            public
            constructor Create(P1,P2,P3: Integer); virtual;
            end;<br>

            TBaseThread_XYZ = class(TBaseThread)
            publich
            constructor Create(P1,P2,P3: Integer); override;
            end;<br>

            procedure RegisterBasethread(Class: TBaseThreadClass);
            begin
            RegisterClass(Class);
            end;<bR>

            function CreateBaseThreadByName(const Name: String; P1,P2,P3: Integer): TBaseThread;
            var
            Class: TClass;
            begin
            Class := GetClass(Name);
            if (Class = nil) or not Class.InheritsFrom(TBaseThread) then
            raise Exception.Create('Class not found');
            Result := TBaseThreadClass(Class).Create(P1, P2, P3);
            end;<br>

            </pre>

            Gruß Hage

            Comment


            • #7
              <pre>
              Hallo,

              ich habe das leider nicht richtig verstanden.
              Aber ich habe folgendes ausprobiert:
              Die Unit, in der ich dem Thread das endgültige "Aussehen" gebe,
              erweitere ich um

              <b>initialization
              RegisterClass(TPersistentClass(TSt7Auslesen));</b>
              dann erweitere ich die besagte Aufruffunktion (andere Unit) wie folgt:
              </pre>
              <b>TempClass := getClass('TSt7Auslesen');<br>
              if (TempClass <> nil) and TempClass.InheritsFrom(TCustomDWConnectAsBDE) then<br>
              TempThead := TCustomDWConnectAsBDE(TempClass).Create(1,2,3);<br ></b>
              leider gibt es beim Registrieren eine Exeption, also gleich beim Aufrufen der Anwendung.<br>
              Ich glaube es liegt daran, weil TThread von TObject abgeleitet ist, und nicht von TPersistent?<br>
              Wenn aber das Registrieren so klappen würde, dann hätten wir erheblich weniger Entwicklungsaufwand, da der Unit mit dem Aufruf nicht alle Units der Threads bekannt sein müssen. Und diese auch sonst nicht ständig verändert werden müsste, wenn ein neuer Thread dazu kommt.

              Helmut
              &#10

              Comment


              • #8
                Dann schreib deine eigene Registrations Routinen, ist vielleicht eh besser so:

                <pre>

                procedure RegisterThread(const Class: TBaseThreadClass);
                function CreateThread(const Name: String; P1,P2,P3: Integer): TBaseThread;<br>

                implementation<br>

                var
                ThreadClasses: TStringList = nil;<br>

                procedure RegisterThread(const Class: TBaseThreadClasss);
                begin
                if ThreadClasses = nil then ThreadClasses := TStringList.Create;
                ThreadClasses.AddObject(Class.ClassName, Pointer(Class));
                end;<br>

                function GetThreadClass(const Name: String): TBaseThreadClass;
                var
                I: Integer;
                begin
                if ThreadClasses = nil then raise Execption.Create('Class not found');
                I := ThreadClasses.IndexOf(Name);
                if I < 0 then raise Exception.Create('Class not found');
                Result := Pointer(ThreadClasses.Objects[I]);
                end;<br>

                function CreateThread(const Name: String; P1, P2, P3: Integer): TBaseThread;
                begin
                Result := GetThreadClass(Name).Create(P1, P2, P3);
                end;<br>

                finalization
                FreeAndNil(ThreadClasses);
                end.<br>

                </pre>

                Gruß Hage

                Comment


                • #9
                  <pre>
                  Hallo Hagen,
                  die Ide ist sehr gut. Nur leider komme ich noch nicht weiter.
                  Folgende habe ich versucht:
                  In jeder Threadunit habe ich ein Abschnitt<b>
                  initialization
                  RegisterThread('TSt7Auslesen', TSt7Auslesen);</b>
                  eingefügt.
                  In einer neuen Unit habe ich die benötigten Funktionen aufgenommen<b>
                  procedure RegisterThread(const Name: String; const TClass: Pointer);
                  begin
                  ThreadClasses.AddObject(Name, TClass);
                  end;

                  function GetThreadClass(const Name: String): Pointer;
                  var
                  I: Integer;
                  begin
                  if ThreadClasses = nil then
                  raise Exception.Create('Class not found');
                  I := ThreadClasses.IndexOf(Name);
                  if I < 0 then
                  raise Exception.Create('Class not found');
                  Result := Pointer(ThreadClasses.Objects[I]);
                  end;</b>
                  Nun der Aufruf<b>
                  procedure startThread(ThreadName: String);
                  var ThreadClass: TCustomDWConnectAsBDE;
                  TempThread: Pointer;
                  begin
                  ThreadClass := GetThreadClass(ThreadName);
                  TempThread := ThreadClass.Create(1,2,3);
                  end;</b>
                  leider tritt im Construktor ein Fehler auf bei:<b>
                  inherited Create(true);</b>
                  dies ist wohl der Aufruf von TThread?
                  Was kann falsch sein??

                  Helmut</pre&gt

                  Comment


                  • #10
                    Deine Verwendung von Pointer muß falsch sein. Ganz wichtig

                    <pre>

                    function StartThread(const ClassName: String, P1, P2, P3: Integer): TBaseThread;
                    begin
                    Result := GetBaseThreadClass(ClassName).Create(P1, P2, P3));
                    end;<br>

                    // das impliziert <br>

                    function StartThread(const ClassName: String; P1, P2, P3: Integer): TBaseThread;
                    var
                    BaseThreadClass: TBaseThreadClass; // <- NICHT Pointer o.a.
                    begin
                    BaseThreadClass := GetBaseThreadClass(ClassName);
                    Result := BaseThreadClass.Create(P1, P2, P3);
                    end; <br>

                    // dafür MUSS aber <br>

                    type
                    TBaseThreadClass = class of TBaseThread;
                    TBaseThread = class(TThread)
                    public
                    constructor Create(P1, P2, P3: Integer); </b> virtual; </b>
                    end;<br>

                    // sein, und demnach<br>

                    type
                    TMyWorkingThread = class(TBaseThread)
                    public
                    constructor Create(P1, P2, P2: Integer); </b> override; </b>
                    end;<br>

                    // clever wäre auch <br>

                    type
                    TBaseThread = class(TThread)
                    public
                    constructor Create(....); virtual;
                    class procedure Register;
                    end;<br>

                    class procedure TBaseThread.Register;
                    begin
                    RegisterBaseThreadClass(Self);
                    end;<br>

                    initialization
                    TWorkingThreadClass.Register;
                    end.<br>

                    </pre>

                    Gruß Hage

                    Comment


                    • #11
                      <pre>

                      <code><font size=2 face="Courier New"><b>unit </b>BaseThread;
                      <br>
                      <b>interface
                      <br>
                      uses </b>Classes;
                      <br>
                      <b>type
                      </b>TBaseThreadClass = <b>class of </b>TBaseThread;
                      <br>
                      TBaseThread = <b>class</b>(TThread)
                      <b>public
                      constructor </b>Create(P1, P2, P3: Integer); <b>virtual</b>;
                      <b>class procedure Register</b>;
                      <b>end</b>;
                      <br>
                      <b>function </b>StartBaseThread(<b>const </b>ClassName: <b>String</b>; P1, P2, P3: Integer): TBaseThread;
                      <br>
                      <b>implementation
                      <br>
                      uses </b>SysUtils;
                      <br>
                      <b>var
                      </b>FBaseThreadClasses: TStringList = <b>nil</b>;
                      <br>
                      <b>constructor </b>TBaseThread.Create(P1, P2, P3: Integer);
                      <b>begin
                      inherited </b>Create(True);
                      <b>end</b>;
                      <br>
                      <b>class procedure </b>TBaseThread.<b>Register</b>;
                      <b>resourcestring
                      </b>sAlreadyRegistered = <font color="#0000FF">'%s ist schon registriert'</font>;
                      <b>begin
                      if </b>FBaseThreadClasses = <b>nil then </b>FBaseThreadClasses := TStringList.Create;
                      <b>if </b>FBaseThreadClasses.IndexOf(ClassName) &gt;= <font color="#0000FF">0 </font><b>then
                      raise </b>Exception.CreateFmt(sAlreadyredistered, [ClassName]);
                      FBaseThreadClasses.AddObject(ClassName, Pointer(Self));
                      <b>end</b>;
                      <br>
                      <b>function </b>StartBaseThread(<b>const </b>ClassName: <b>String</b>; P1, P2, P3: Integer): TBaseThreadClass;
                      <br>
                      <b>procedure </b>Error;
                      <b>resourcestring
                      </b>sNotRegistered = <font color="#0000FF">'%s ist nicht registriert'</font>;
                      <b>begin
                      raise </b>Exception.CreateFmt(sNotRegistered, [ClassName]);
                      <b>end</b>;
                      <br>
                      <b>var
                      </b>I: Integer;
                      BaseThreadClass: TBaseThreadClass;
                      <b>begin
                      if </b>FBaseThreadClasses = <b>nil then </b>Error;
                      I := FBaseThreadClasses.IndexOf(ClassName);
                      <b>if </b>I &lt; <font color="#0000FF">0 </font><b>then </b>Error;
                      BaseThreadClass := Pointer(FBaseThreadClasses.Objects[I]);
                      <b>if </b>BaseThreadClass = <b>nil then </b>Error;
                      <b>if not </b>BaseThreadClass.InheritsFrom(TBaseThread) <b>then </b>Error;
                      Result := BaseThreadClass.Create(P1, P2, P3);
                      <b>end</b>;
                      <br>
                      <b>initialization
                      finalization
                      </b>FreeAndNil(FBaseThreadClasses);
                      <b>end</b>.
                      </font>
                      </code></pre&gt

                      Comment


                      • #12
                        <pre>

                        <code><font size=2 face="Courier New"><font color="#008080"><i>// nun die Anwendung von obigem
                        <br>
                        </i></font><b>unit </b>Unit1;
                        <br>
                        <b>interface
                        <br>
                        uses </b>BaseThread;
                        <br>
                        <b>type
                        </b>TWorkingThread = <b>class</b>(TBaseThread)
                        <b>public
                        constructor </b>Create(P1, P2, P3: Integer); <b>override</b>;
                        <b>end</b>;
                        <br>
                        <b>implementation
                        <br>
                        constructor </b>TWorkingThread.Create(P1, P2, P3: Integer);
                        <b>begin
                        inherited </b>Create(P1, P2, P3);
                        <b>end</b>;
                        <br>
                        <b>initialization
                        </b>TWorkingThread.<b>Register</b>;
                        <b>end</b>.
                        </font>
                        </code></pre&gt

                        Comment


                        • #13
                          <pre>

                          <code><font size=2 face="Courier New"><font color="#008080"><i>// und der Test
                          <br>
                          </i></font><b>procedure </b>TestThread;
                          <b>var
                          </b>Thread: TBaseThread;
                          <b>begin
                          </b>Thread := StartBaseThread(<font color="#0000FF">'TWorkingThread'</font>, <font color="#0000FF">1</font>, <font color="#0000FF">2</font>, <font color="#0000FF">3</font>);
                          Assert( Thread &lt;&gt; <b>nil </b>);
                          Assett( Thread.InheritsFrom(TBaseThread) );
                          <b>end</b>;
                          </font>
                          </code></pre&gt

                          Comment


                          • #14
                            SUUUPER,<br>
                            so gehts<br>
                            Helmu

                            Comment

                            Working...
                            X