Reflection und Funktionsüberladung



  • Hallo zusammen,

    ich frage mich gerade, ob und wie man sowas in C# umsetzen kann:

    public class MyClass
    {
       public UInt32   ID  { get; set; }
       public string Name  { get; set; }
       public double Value { get; set; }
    };
    
    public class ObjectReader
    {
       public MyClass ReadMyClass()
       {
          MyClass retval = new MyClass();
          PropertyInfo[] properties = retval.GetType().GetProperties( BindingFlags.Public | BindingFlags.Instance );
          foreach( PropertyInfo pi in properties )
          {
             // Hier den Typ der Property erkennen, lokale Variable des Datentyps anlegen, Wert lesen und setzen.
             // Wie kann ich den Datentyp der  property benutzen, um die richtige Read-Überladung aufzurufen?
             // Ich möchte das, wenn möglich, ohne if-then-else Kaskaden über den Namen des Typen lösen.
             ? tmp = ReadValue( ? ); 
             pi.SetValue( retval, tmp );
          }
       }
       // div. ReadValue Überladungen
      bool ReadValue( bool dummy )
      {
      }
      bool ReadValue( Int16 dummy )
      {
      }
      // usw.   
    }
    


  • Ich würde sagen per Reflection die passende ReadValue Methode raussuchen und dann ebenso per Reflection aufrufen. Zurück bekommst du dann ein Object das du für PropertyInfo.SetValue verwenden kannst. Wobei ich vermute dass es einfacher wird wenn du die Dummy-Parameter entfernst. Dabei musst du dann vermutlich unterschiedliche Namen für die ReadValue Methoden verwenden. Das sollte aber nicht stören, du kannst ja nach allen Methoden durchgehen deren Name mit ReadValue anfängt.

    Ich hab aber schon lange nichts mehr mit C# gemacht und noch länger nichts mehr mit Reflection. Kann sein dass es wesentlich einfacher und/oder performanter geht.



  • Danke für den Hinweis, ich hatte gehofft, dass das iwie typsicher zur Compile Time erledigt werden kann. Hab´s jetzt so gelöst:

    public class ObjectReader
    {
       public T ReadObject<T>() where T : class, new()
       {
          T retval = new T();
          PropertyInfo[] properties = typeof( T ).GetProperties( BindingFlags.Instance | BindingFlags.Public );
          foreach( PropertyInfo pi in properties )
          {
              pi.SetValue( retval, ReadValue( pi.PropertyType ) );
          }
          return retval;
       }
    
       object ReadValue( Type type )
       {
          if( type == typeof( bool ) ) return ReadBoolean();
          else if( type == typeof( Int16 ) ) return ReadInt16();
          ...
        }
    }
    

    Ist halt unschön, dass nicht-unterstützte Datentypen erst zur Laufzeit erkannt werden und nicht schon zur Compile Time.



  • Tja das ist halt Reflection, das ist nur zur laufzeit und nicht zur compile time



  • @firefly
    Ist trotzdem nicht schön, da alle Informationen schon zur Compile Time zur Verfügung stehen. Naja, machste nix, musste gucken zu.



  • @DocShoe Ja das sieht wesentlich besser aus als mein Vorschlag 🙂

    Ist trotzdem nicht schön, da alle Informationen schon zur Compile Time zur Verfügung stehen.

    Eh. Aber das ist halt der Unterschied zwischen Generics und Templates. Über "T" ist im Generic nur das bekannt was als Constraint mitgegeben wurde. Hier also dass es ne "class" ist und dass diese einen Default-Konstruktor hat.


Log in to reply