Announcement

Collapse
No announcement yet.

Instanz aus einem Assembly

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

  • Instanz aus einem Assembly

    Hallo,

    eine mit c# entwickelte DLL (Assembly) enthält folgendes Konstrukt:
    <PRE>
    public class MyClass
    {
    public CBasisklasse InitIt()
    {
    return new CAbgeleiteteKlasse();
    }
    }
    </PRE>

    Im Hauptprogramm wird das Assembly über Assembly.Loadfrom geladen; Über Reflection (Type -> GetType(), Activator.CreateInstance, MethodInfo, etc.) wird schließen MethodInfo.Invoke aufgerufen.

    Wie komme ich nun im Hauptprogramm an die Instanz von CAbgeleitetetKlasse heran?

    Viele Grüße Hans-Peter Tschan

  • #2
    Nachtrag:

    1) CAbgeleiteteKlasse ist von CBasisklasse und einem Interface abgeleitet

    2) Prinzipiell funktioniert die Instanzierung von CAbgeleiteteteKlasse - nur, wenn ich das Result von Invoke umwandeln will, wird eine NullReferenceExceptionen ausgelöst

    3) Wenn die Methode Initit einen nativen Typ, z.B. "object" oder "Array" instanziert, dann funktionierts.

    Viele Grüße Hans-Peter Tscha

    Comment


    • #3
      Hallo,

      da die .NET-Sprachen im Gegensatz zu älteren Sprachen deutlich mehr Wert auf die Typübereinstimmung legen, muss man für derartige Aufgaben auf das <i>Abstract Factory Pattern</i> zurückgreifen. Die folgende Beispiel-Klasse kann Instanzen von anderen Klassen über einen gemeinsamen <b>Interface</b>-Rückgabewert erzeugen: <i><a href="/webx?13@@.1dd04f40/1">Andreas Kosch "Dynamische Erzeugung von Instanzen" 16.07.2003 16:51</a></i&gt

      Comment


      • #4
        Hallo Andreas,

        leider bringt mich das nicht weiter: Es scheitert beim Cast von "Object" zu "CBasisklasse" (bzw. auch zu IBasisinterface) nach dem Aufruf der Methode MethodInfo.Invoke. Hast Du noch einen Tip?

        Viele Grüße Hans-Peter Tscha

        Comment


        • #5
          Hallo Andreas,<BR>
          ich habe das selbe Problem und weiß auch keine Lösung!<BR>
          Siehe auch unter <B>Probleme mit GetType().Equals(...)</B><BR>
          Gruß Christop

          Comment


          • #6
            Hallo,

            &gt;Hast Du noch einen Tip?

            das Prinzip funktioniert, in diesem Fall (Activator.CreateInstance) müssen wir jedoch die strengen Regeln der .NET-Typprüfung einhalten, indem die Interface-Deklaration in eine <b>separate</b> Assembly ausgelagert wird, die von <b>beiden</b> Assemblies (Class-Assembly + Programm-Assembly) eingebunden wird. Erst dann ist für .NET ein Type auch wirklich "identisch". Das folgende Beispiel demonstriert dies:

            <b>A) Gemeinsame Interface-Assembly</b><br>
            In dieser Class-Library wird nur die Interface-Struktur deklariert und als separate DLL kompiliert:
            <pre>
            <b>using</b> System;
            <br>
            <b>namespace</b> OSIntfAsm
            {
            <b>public</b> <b>interface</b> IOSBaseInterface
            {
            <b>string</b> DoWork(<b>string</b> sInput);
            }
            }
            </pre>
            <b>B) Klasse implementiert dieses Interface</b><br>
            In VS.NET wird im Solution Explorer unter dem Zweig <i>References</i> ein Verweis zur Interface-Assembly (A) hinzugefügt. Die Klasse holt sich somit den Aufbau des zu implementierten Interfaces aus der "fremden" Assembly:
            <pre>
            <b>using</b> System;
            <br>
            <b>namespace</b> OSClsAsm
            {
            <b>public</b> <b>class</b> OSCls: OSIntfAsm.IOSBaseInterface
            {
            <b>public</b> OSCls()
            {
            }

            <b>public</b> <b>string</b> DoWork(<b>string</b> sInput)
            {
            <b>return</b> sInput + <font color="#9933CC">&quot; OSClsAsm&quot;</font>;
            }
            }
            }
            </pre>
            <b>C) Programm ruft die Klasse (B) auf</b><br>
            In VS.NET wird im Solution Explorer dem Zweig <i>References</i> nur ein Verweis auf die Interface-Assembly (A) hinzugefügt. Die über Reflection erzeugten Objektinstanz vom Type <b>object</b> darf dann Dank der gemeinsam genutzten Interface-Assembly in den Interface-Type umgetauscht werden, so dass für alle folgenden Aufrufe die frühe Bindung zur Verfügung steht:
            <pre>
            <b>private</b> <b>void</b> button1_Click(<b>object</b> sender, System.EventArgs e)
            {
            OSIntfAsm.IOSBaseInterface aObj;
            aObj = <b>new</b> OSClsAsm.OSCls() <b>as</b> OSIntfAsm.IOSBaseInterface;
            MessageBox.Show(aObj.DoWork(<font color="#9933CC">&quot;Das ist ein Test&quot;</font>));
            }
            </pre>

            bitte warten.. wird noch ergänzt..

            Comment


            • #7
              Hallo,

              &gt;Hast Du noch einen Tip?

              das Prinzip funktioniert, in diesem Fall (Activator.CreateInstance) müssen wir jedoch die strengen Regeln der .NET-Typprüfung einhalten, indem die Interface-Deklaration in eine <b>separate</b> Assembly ausgelagert wird, die von <b>beiden</b> Assemblies (Class-Assembly + Programm-Assembly) eingebunden wird. Erst dann ist für .NET ein Type auch wirklich "identisch". Das folgende Beispiel demonstriert dies:

              <b>A) Gemeinsame Interface-Assembly</b><br>
              In dieser Class-Library wird nur die Interface-Struktur deklariert und als separate DLL kompiliert:
              <pre>
              <b>using</b> System;
              <br>
              <b>namespace</b> OSIntfAsm
              {
              <b>public</b> <b>interface</b> IOSBaseInterface
              {
              <b>string</b> DoWork(<b>string</b> sInput);
              }
              }
              </pre>
              <b>B) Klasse implementiert dieses Interface</b><br>
              In VS.NET wird im Solution Explorer unter dem Zweig <i>References</i> ein Verweis zur Interface-Assembly (A) hinzugefügt. Die Klasse holt sich somit den Aufbau des zu implementierten Interfaces aus der "fremden" Assembly:
              <pre>
              <b>using</b> System;
              <br>
              <b>namespace</b> OSClsAsm
              {
              <b>public</b> <b>class</b> OSCls: OSIntfAsm.IOSBaseInterface
              {
              <b>public</b> OSCls()
              {
              }
              <br>
              <b>public</b> <b>string</b> DoWork(<b>string</b> sInput)
              {
              <b>return</b> sInput + <font color="#9933CC">&quot; OSClsAsm&quot;</font>;
              }
              }
              }
              </pre>
              <b>C) Programm ruft die Klasse (B) auf</b><br>
              In VS.NET wird im Solution Explorer dem Zweig <i>References</i> nur ein Verweis auf die Interface-Assembly (A) hinzugefügt. Die über Reflection erzeugten Objektinstanz vom Type <b>object</b> darf dann Dank der gemeinsam genutzten Interface-Assembly in den Interface-Type umgetauscht werden, so dass für alle folgenden Aufrufe die frühe Bindung zur Verfügung steht:
              <pre>
              <b>string</b> sDLL = @<font color="#9933CC">&quot;C:\Temp\Out\VSNET2003\Reflec tionInterface\OSClsAsm\bin\Debug\OSClsAsm.dll&quot ;</font>;
              <br>
              <b>private</b> <b>void</b> button1_Click(<b>object</b> sender, System.EventArgs e)
              {
              System.Reflection.Assembly aAsm;
              aAsm = System.Reflection.Assembly.LoadFrom(sDLL);
              Type aType = aAsm.GetType(<font color="#9933CC">&quot;OSClsAsm.OSCls&quot;</font>);
              <b>Object</b> aObj = Activator.CreateInstance(aType);
              OSIntfAsm.IOSBaseInterface aObjIntf;
              aObjIntf = aObj <b>as</b> OSIntfAsm.IOSBaseInterface;
              MessageBox.Show(aObjIntf.DoWork(<font color="#9933CC">&quot;Das ist ein Test&quot;</font>));
              }
              </pre>
              Die folgende Abbildung zeigt den Aufbau

              Comment


              • #8
                Hallo Andreas,

                genau das war's. Wie wohl so mancher vor mir, musste ich die Erfahrung machen, dass VS. NET bei "Projekt hinzufügen" eine Kopie der .cs-Datei anlegt -> nicht alles was gleich scheint, ist auch gleich...Vielen Dank für Deine Hilfe!

                Viele Grüße Hans-Peter Tscha

                Comment


                • #9
                  Vielen Dank Andreas,<BR><BR>
                  bei mir hat das nun auch funktioniert!<BR>
                  Darauf muß man erstmal kommen, das Interface in eine eigene Assembly zu stecken ;-).<BR>
                  Gruß Christop

                  Comment


                  • #10
                    Hallo,

                    &gt;..das Interface in eine eigene Assembly zu stecken ..

                    für die CLR ist ein Type nur dann identisch, wenn die Bestandteile <i>Assembly-Name</i> (bzw. Strong Name) und der Typ-Namen übereinstimmen. Das steht mehrfach in der Doku, aber meistens fehlt dort der Hinweis auf die Auswirkungen ;-

                    Comment

                    Working...
                    X