Announcement

Collapse
No announcement yet.

dynamisches casting

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

  • dynamisches casting

    gibt es eine möglich keit zur laufzeit dynamisch zu casten? also etwas im sinne von:

    Code:
    class A
    {
    
    }
    
    int main()
    {
    A a = new A();
    
    object aObject = a;
    
    A dyncast = (aObject.GetType())(aObject);
    
    }
    wenn es sowas gibt würde mir das unwarschienlich helfen.

    mfg
    Zebes

  • #2
    Hallo Zebes,

    nein das geht definitiv nicht. Normalerweise ist Dein Bedürfnis ein starkes Anzeichen dafür, dass Du ein Designfehler vorliegen hast.

    Verwende Interfaces anstatt dynamisch casten zu lassen oder fasse logische Gruppen zu abstrakten Basisklassen zusammen und verwende diese.

    Grob gesehen solch ein Aufbau:

    Code:
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace TestConsole
    {
        public interface IMyIntInterface
        {
            int IntegerValue { get; }
        }
    
        public interface IMyStringInterface
        {
            string StringValue { get; }
        }
    
        public interface IMyCombinedInterface : IMyIntInterface, IMyStringInterface
        { }
    
        public class A : IMyIntInterface, IMyStringInterface
        {
            private int m_iMyIntegerValue = 33;
            private string m_sMyStringValue = "Class A";
    
            #region IMyInterface Members
    
            public int IntegerValue
            {
                get { return m_iMyIntegerValue; }
            }
    
            #endregion
    
            #region IMyStringInterface Members
    
            public string StringValue
            {
                get { return m_sMyStringValue; }
            }
    
            #endregion
        }
    
        public class B : IMyCombinedInterface
        {
            private int m_iMyIntergerValue = 44;
            private string m_sMyStringValue = "Class B";
    
            #region IMyInterface Members
    
            public int IntegerValue
            {
                get { return m_iMyIntegerValue; }
            }
    
            #endregion
    
            #region IMyStringInterface Members
    
            public string StringValue
            {
                get { return m_sMyStringValue; }
            }
    
            #endregion
        }
    
        public class TestClass
        {
            public TestClass()
            {
                A classA = new A();
                B classB = new B();
    
                TestMethod(classA);
                TestMethod(classB);
    
                TestMethod2(classA);
                TestMethod2(classB);
            }
    
            public void TestMethod(object p_oParam)
            {
                // hier wird z.B. nur die Int Funktionalität gebraucht:
                IMyIntInterface intFace = (IMyIntInterface)p_oParam;
    
                Console.WriteLine("IntVal: " + intFace.IntegerValue);
            }
    
            public void TestMethod2(object p_oParam)
            {
                // hier wird z.B. die kombinierte Funktionalität gebraucht:
                IMyCombinedInterface intFace = (IMyCombinedInterface)p_oParam;
    
                Console.WriteLine("Combined value: " + intFace.IntegerValue + " - " + intFace.StringValue);
            }
        }
    }
    Ich denke so wird es vielleicht klarer?

    Grüße
    _ntr_

    Edit:
    Ich hab hier absichtlich einen Fehler eingebaut, deshalb wird es eine Laufzeitexception geben, wenn Du mir sagen kannst warum, dann hast Du Interfaces besser verstanden ;-)

    Comment


    • #3
      Hallo,

      es ist mir schleierhaft, was Du erreichen willst und in welcher Situation so etwas gut sein soll. Als Programmierer bist Du verantwortlich dafür, was wann geschehen soll. Aber Du hast sicher gute Gründe (die uns verschweigen willst).

      Aber schau einmal unter TypeDescriptor.GetConverter-Methode und den dabei genannten anderen Klassen nach; vielleicht findest Du dort etwas Passendes.

      Gruß Jürgen

      PS. Ein Beispiel, wofür so etwas gut ist, ist die Konvertierung Font <-> String:
      Code:
      using System.ComponentModel;
      //  Deklaration
      Font myFont;
      string myFontString;
      //  Konvertierungen (es gibt auch noch ein paar Varianten)
      myFontString = TypeDescriptor.GetConverter(typeof(Font)).ConvertToInvariantString(myFont);
      myFont = (Font)TypeDescriptor.GetConverter(typeof(Font)).ConvertFromInvariantString(myFontString);
      PS2. Hallo Norman-Timo, so trifft man sich wieder.
      Zuletzt editiert von Jürgen Thomas; 19.06.2007, 11:42.

      Comment


      • #4
        hauptsächlich habe ich gerade das problem das ich objekte zur laufzeit aus einem assembley laden will. im moment funktioniert das auch da ich das geladene object an ein object einer abstracten basisklasse weiter gebe halt objektorientierung.

        nun will ich aber objekte laden die ein konkretes objekt erhalten sollen das ich vorher geladenhabe. nun habe ich die möglichkeit im konstruktor explizit zu casten, da ich ja weis was ich übergeben bekommen sollte oder ich finde eine möglichkeit dynamisch zu casten was ich einfach schöner fänd.

        oder ich biete einfach 2 konstruktoren an, einen der object entgegen nimmt und einen der das konkrete objekt bekommt.

        mfg
        Zebes

        Comment


        • #5
          Hallo Zebes,

          so ganz habe ich es immer noch nicht verstanden. Auch in Deinem Fall, dass Du Klasseninstanzen aus dynamischen Assemblies erstellen möchtest, würde ich den Weg über Interfaces gehen. Damit die Typsicherheit gewährleistet ist, würde ich vor Erzeugen einer Instanz auf ein bestimmtes Interface prüfen.

          Möchtest Du ein Plugin-Konzept aufbauen? Dann nochmal der Tipp: Nimm Interfaces.

          Wenn Du eine Klasse mittels Reflection erzeugst, dann kannst Du nicht dynamisch casten (entweder hart oder gar nicht). Solltest Du gar nicht casten, dann kannst Du immer nur über Reflection auf Methoden und Eigneschaften zugreifen, und das an JEDER Stelle wo Du Zugriff brauchst.

          Also ein Cast auf eine Basisklasse oder auf Interfaces, das muss für angenehmes Programmieren sein. Templates wie in C++ gibt es in dieser Form in C# nicht.

          Grüße
          _ntr_

          Comment


          • #6
            templates wären an dieser stelle auch blöde da die typen ja zur laufzeit bekannt sein müßten. ich prüfe gerade ob die geladenen objekte bestandteil einer bestimmten klasse sind somit ist die typsicherheit auch gegeben. ob ich das ganze statt auf abstrakte klassen auf interfaces um baue weiß ich nciht aber es wurd emir schon mehrfach empfohlen.

            also werde ich dann im konstruktor wohl doch expliziet casten müssen und das unabhängig davon ob ich eine abstacte klasse oder ein interface verwende.

            danke an dieser stelle für eure antworten
            mfg
            Zebes

            Comment


            • #7
              Hallo Zebes,

              lass mich noch hinterfragen, welchen Konstruktor Du mit
              also werde ich dann im konstruktor wohl doch expliziet casten müssen
              meinst?

              Ist es die Klasse, die Du aus Deiner Assembly instanziieren willst? Oder was für einen Konstruktor ist gemeint?

              _ntr_

              Comment


              • #8
                also als beispiel was ich nun vor habe:

                Code:
                class abstract _A
                {
                }
                
                class A : _A
                {
                
                }
                
                class B
                {
                    A myA;
                
                    B(object item)
                    {
                         B((A)item);
                    }
                    B(A item)
                    {
                         myA = item;
                    }
                }
                
                //... iregend wo im programm
                
                _A ein_A_object;
                B ein_B_object;
                
                ein_A_object = Createinstanz();
                ein_B_object = Createinstanz(new  object[] {ein_A_Object});
                
                //...
                ich habe jetzt hier die typprüfung ausgelassen und der aufruf Creatinstanz ist auch nicht korrekt, aber es sollte klar sein was ich machen will.

                am liebsten wäre es mir wenn ich den konstruktor B(object item) mir irgend wie sparen könnte.

                mfg
                Zebes

                Comment


                • #9
                  Hallo Zebes,

                  gut, dass ich nochmal nachfrage ;-)

                  Ich bin mir nicht sicher, welcher von den beiden folgenden Methoden Dir helfen könnte, da ich den Rest Deines Programmes nicht kenne:

                  A) Wenn Du aus einem bestimmten Kontext heraus eine bestimmte Instanz erstellt bekommen möchtest, dann hilft Dir das AbstractFactory-Pattern, z.B. hier zu finden:
                  Design Pattern: Abstract Factory

                  B) Wieso brauchst Du in Deinem Fall überhaupt den "Object"-Konstruktor, warum übergibst Du Dein Parameter als Objekt und nicht als "A"? Das habe ich vorhin gemeint mit abstrakter Klasse oder Interface, weil Du hier anstatt "object" ein "IMyInstance" (oder was für ein Interface/Abstr. Klasse auch immer) übergeben kannst.

                  Viele Grüße
                  _ntr_

                  EDIT: Grammatik

                  Comment


                  • #10
                    ich benötige den object konstruktor nicht zwingend. ich hätte auch eine ebene höher gehen können und einen B(_A) konstruktor nehmen können. das ergebnis wäre das gleiche. leider kann c#(ich wüßte auch nicht, dass eine andere sprache das kann) nicht impliziet "hochcasten"

                    ach ja ich hatte deine frage von vorhin noch nicht beantwortet. ja es soll ein plugin konzept werden.

                    aber ob ich nun hier mit abstracten klassen arbeite oder mit interfaces sollte erst mal keinen unterschied machen, auch wenn ich mir das generell mal überlegen sollte.

                    ich übergebe den parameter als object, weil ich den typ ja nicht kenne. ich weiß nur das es eine subklasse von _A sein muß. wenn ich interfaces verwende muss es eine subklasse von zb I_A sein bzw dieses interface implementieren. da es ein plugin system ist, können die konkreten objekte die erstellt werden von jedem typ sein, klar ist nur das sie entweder von einer von mir vorgegebenen klasse abgeleitet sind oder halt ein interface implementieren.

                    nun habe ich aber objecte, die den konkreten typ kennen da sie auf spezifische komponenten zugreifen müssen, desshalb reicht ein reines interface auch nicht.

                    ich werde mit das entwurfsmuster mal genauer anschauen, danke für den tip.

                    mfg
                    Zebes
                    Zuletzt editiert von Zebes; 19.06.2007, 16:29.

                    Comment


                    • #11
                      Hallo Zebes,

                      ich weiß nur das es eine subklasse von _A sein muß.
                      Genau das ist das, worauf ich hinaus will: Du kannst anstatt object vom Typ _A ausgehen, also ein _A übergeben, anstatt ein object.

                      Ein Plugin Konzept geht davon aus, dass das Plugin einem entsprechend von Dir vorgegebenen Schema entsprechen MUSS. Also eben von einer Dir vorgegebenen abstrakten Klasse geerbt, oder ein von Dir vorgegebenes Interface muss implementiert sein (beides ist hier fast äquivalent).

                      Also könnte ein Plugin-Konzept so aussehen, dass Du vorgibst, dass ein Plugin folgendes Interface-Schema implementiert:

                      Code:
                      public interface IMyImagePlugin
                      {
                         Image GetImage(IMainPrgInterface sender);
                      }
                      Im Code würdest Du dann durch alle Klassen der Plugin-Dll gehen und prüfen, ob eine Klasse das Interface "IMyImagePlugin" implementiert, wenn ja, dann erstellst Du eine Instanz via Reflection, und castest das zurückerhaltene Objekt direkt zu "IMyImagePlugin".

                      Ab dann verwendest Du in Deinem Programm nur noch das Objekt via das Interface, z.B. indem Du einen PluginContainer bereitstellst, der nur ImagePlugins enthält, vielleicht in einem Dictionary mit Key, der den Namen der Assembly enthält (z.B.)

                      Dann kannst Du bei Bedarf das Plugin "ausführen" lassen, indem Du die Methode GetImage() aufrufst...

                      Falls das Plugin Zugriff auf Bestandteile aus dem Hauptprogramm braucht, solltest Du auch hier dem Plugin ein Interface als "sender" übergeben, mit dem es konkrete Aufgaben erledigen kann.

                      Deshalb ist ein dynamisches Casten normalerweise nicht notwendig.

                      Bitte beachte: jedesmal wenn ich hier von Interfaces rede, kannst Du auch abstrakte Klassen nehmen (auch wenn ich Interfaces bevorzuge), das würde funktional auch gehen.

                      Grüße
                      _ntr_

                      Comment


                      • #12
                        ja vielen dank, dass ist im prinzip das was ich nun auch gemacht hätte.

                        das problem für mich war einfach, dass meine Plugins Plugins enthalten und diese auch aus meinem hauptprogramm geladen werden. also im prinzip sowas:
                        Code:
                                     Hauptplugin1                              Hauptplugin2
                                             |                                      |
                               ------------------------                   ---------------------
                               |          |           |                   |         |          |
                        SubPlugin1  SubPlugin2   SubPlugin3        SubPlugin1  SubPlugin2  SubPlugin3
                        das Hauptprogramm kennt nur ein interface oder eine abstracte Klasse von HauptPlugin. Ein Hauptplugin in kennt wiederum nur ein interface oder eine abstracte Klasse von SubPlugin. allerdings kennt ein SubPlugin sein konkretes HauptPlugin, da dieser spezielle informationen für die SubPlugins bereitstellen soll.

                        ich denke aber es wäre besser wenn die HauptPlugins sich ihre SubPlugins selber laden. Dann weiß ich auch um welches Hauptplugin in es sich handelt und brauche nicht zu casten.

                        mfg
                        Zebes

                        Comment


                        • #13
                          Hallo Zebes,

                          ich denke aber es wäre besser wenn die HauptPlugins sich ihre SubPlugins selber laden. Dann weiß ich auch um welches Hauptplugin in es sich handelt und brauche nicht zu casten.
                          ja das wäre die logische Fortsetzung des Plugin-Konzeptes. Ich denke jetzt hast Du mich auch vollständig verstanden, und ich vermute, dass Du nun auf dem richtigen Weg bist ;-)

                          Viele Grüße,
                          _ntr_

                          Comment

                          Working...
                          X