Benutzerdefinierte, komplizierte, dynamische Reflektionslösung - C #

Ich verwende viele benutzerdefinierte Klassen, für die ich Beispiele erläutern und veröffentlichen werde. Nachdem ich erklärt habe, was sie alle tun, werde ich versuchen, die Bedingungen, unter denen mein Fehler auftritt, klar zu beschreiben.

Zunächst verwende ich ein PropertyGrid, um die Eigenschaften verschiedener Objekttypen anzuzeigen. Da die Standardbindung des PropertyGrid nicht so aussagekräftig war, wie ich es wollte, habe ich einige benutzerdefinierte Klassen erstellt, die ich als "Anzeige" -Klassen bezeichnen werde. Diese Anzeigeklassen werden erstellt, indem ein Objekt übergeben und dann Eigenschaften erstellt werden, die gut formatierte Zeichenfolgen und Beschreibungen für die öffentlichen Eigenschaften (und in einigen Fällen Methoden) des übergebenen realen Objekts zurückgeben.

Ich werde dies mit einem abgekürzten Beispielcode demonstrieren:

Hier ist ein Beispiel für ein Objekt, das ich in meinem PropertyGrid anzeigen möchte:

public class Joint
{
   public Joint(...)
   {...}

   //properties
   public string Name { get; set;}
   public CustomObject CC { get; set;}
   public List<CustomObject> Custom List { get; set;}
}

Die Zeichenfolgeneigenschaft "Name" wird im PropertyGrid gut angezeigt. Das CustomObject und die Liste wurden jedoch nicht auf eine Weise angezeigt, die mir sehr benutzerfreundlich erschien.

Also habe ich versucht, eine Lösung zu erstellen, indem ich diese Klasse geschrieben habe:

public class DisplayJoint
{       

   private Joint _jnt;

   public DisplayJoint(Joint jnt)
   {
      _jnt = jnt;
   }

   //properties
   public string Name {  get { return _jnt.Name; } }

   [TypeConverterAttribute(typeof(ExpandableObjectConverter))]
   public DisplayCustomObject CC {  get { return new DisplayCustomObject(_jnt.CC); } }

   [TypeConverterAttribute(typeof(ExpandableObjectConverter))]
   public List<CustomObject> CustomList { get; set;}
}

Wie Sie im obigen Code sehen können, habe ich spezielle DisplayClasses sowohl für meine Joint-Klasse als auch für meine CustomObject-Klasse erstellt. In meinem Projekt gibt es viele, viele verschiedene Arten von Objekten, die dieselben überlappenden Anzeigeklasseneigenschaften erfordern.

Oben sehen Sie die Linien, die ich über den letzten beiden Eigenschaften hinzugefügt habe

[TypeConverterAttribute (typeof (ExpandableObjectConverter))]

Diese Zeile löst mein Problem, das CustomObject so anzuzeigen, wie ich es im propertiesGrid haben möchte (fast ... dazu später mehr). Bei meiner Eigenschaft "Benutzerdefinierte Liste" funktioniert dies jedoch nicht auf die gleiche Weise. In der benutzerdefinierten Liste werden nur Anzahl und Kapazität (die tatsächlichen Eigenschaften der Liste) angezeigt. Es ist sinnvoll, warum dies so ist, aber es war nicht das, was ich wollte. Ich wollte das tatsächlich enthaltene Objekt in der Liste sehen.

Also hier ist meine komplizierte Lösung, die zunächst ausdiese Frage:

Ich verwende zwei Klassen, um der PropertyGrid-Bindungsliste Objekte in Form von Eigenschaften dynamisch hinzuzufügen. Die erste (CustomClass) kann seinhier heruntergeladen. Es wird verwendet, um Eigenschaften dynamisch zu erstellen. Die zweite Klasse (DisplayIEnumerable), die ich verwende, ist von der ersten abgeleitet und kann gefunden werdenHier.

Die DisplayIEnumerable-Klasse durchläuft die Listenobjekte und fügt sich selbst eine Eigenschaft mit den Informationen hinzu, die in jedem Objekt enthalten sind. Eine DisplayClass wird übergeben, um genau zu definieren, wie diese Objekteigenschaften im Raster dargestellt werden sollen.

Bis zu diesem Punkt funktioniert alles super! Wie aus diesem Bild hervorgeht (Bild wurde nicht mit den angegebenen Klassen erstellt. Zeichenfolgen sind in den von mir verwendeten Klassen unterschiedlich formatiert. Der Formatierungscode wurde entfernt, damit Sie sich besser auf den relevanten Code konzentrieren können:

Jetzt nach diesem langen Intro die eigentliche Frage. Unter Verwendung der obigen Techniken möchte ich eine Klasse schreiben, die CustomObjects dynamisch verarbeiten kann, für die ich keine eindeutigen Anzeigeklassen geschrieben habe. Ich beabsichtige, diesen Code für diejenigen zu belassen, die die Anwendung zum Testen verwenden, damit sie effektiver testen können, ohne dass für jedes CustomObject meines Unternehmens eine vollständige Anzeigeklasse erforderlich ist. (Es gibt Hunderte) Stattdessen hoffe ich, dass durch das Binden des propertyGrid mit der folgenden Klasse alle Eigenschaften, die Listen und CustomObjects sind, die über entsprechende DisplayClasses verfügen, an ihre Stelle gebunden werden können.

Hier ist die Klasse, die ich bereits ausprobiert habe und mit der ich einen Fehler habe. Ich habe noch nicht versucht, das Ersetzen von Listen durch meine DisplayIEnumerable-Klasse zu implementieren. Ich wollte, dass die grundlegenden Funktionen zuerst funktionieren:

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Reflection;
using System.Collections;
using System.Windows.Forms;

   internal class DisplayObject : CustomClass<T>
   {
      #region Variables
      protected T _obj;
      #endregion

      #region Constructor
      public DisplayObject(T obj)
      {
         if (obj != null)
         {
            try
            {
               Type currentType = typeof(T);
               foreach (PropertyInfo propertyInfo in currentType.GetProperties())
               {
                  Attribute[] attributes = new Attribute[1];
                  if (propertyInfo.GetType() is IEnumerable)
                     attributes[0] = new TypeConverterAttribute(typeof(ExpandableObjectConverter));
                  else
                     attributes[0] = null;
                  this.Add(new CustomProperty(propertyInfo.Name, propertyInfo, propertyInfo.GetType(), false, true, attributes));
               }
            }
            catch
            {
               MessageBox.Show("Failure!");
            }
         }
      }
      #endregion

      #region Properties
      [Browsable(false)]
      public object Item
      {
         get { return _obj; }
         set { _obj = value; }
      }
      #endregion
   }

Bei der Ausführung wird das PropertyGrid wie folgt angezeigt:

Wenn Sie jedoch auf den Erweiterungspfeil klicken, geschieht nichts und der Pfeil verschwindet:

Was stimmt nicht mit der obigen Klasse, das stimmt nicht mit meiner DisplayIEnumerable-Klasse, die diese Abweichung im Verhalten verursacht?

Ich verwende die DisplayObject-Klasse wie folgt (innerhalb einer DisplayClass):

  [TypeConverterAttribute(typeof(ExpandableObjectConverter))]
  public DisplayObject EndJoint { get { if (_member.bcEnd != null) { return new DisplayObject(_member.EndJoint); } else return null; } }

Danke im Voraus! Ich bin sehr beeindruckt, wenn jemand diese Frage beantwortet.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage