Solução de Reflexão Dinâmica, Complicada e Personalizada - C #

Eu tenho muitas classes personalizadas que estou usando que vou explicar e postar exemplos de. Depois de explicar o que todos eles fazem, tentarei descrever claramente as condições sob as quais meu bug está acontecendo.

Primeiro, estou usando um PropertyGrid para exibir as propriedades de vários tipos diferentes de objetos. Como a ligação padrão do PropertyGrid não era tão descritiva quanto eu queria, criei algumas classes personalizadas às quais me referirei como classes "Display". Essas classes de exibição são construídas passando-se um objeto e, em seguida, criando propriedades que retornam cadeias de caracteres bem formatadas e descrições para as propriedades públicas (e, em alguns casos, métodos) do objeto real que foi passado.

Vou demonstrar isso com algum código de exemplo abreviado:

Aqui está um exemplo de um objeto que eu quero exibir no meu PropertyGrid:

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

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

A propriedade string "Name" é exibida corretamente no PropertyGrid. No entanto, o CustomObject e List não são exibidos de maneira que pareça muito amigável para mim.

Então eu tentei criar uma solução escrevendo esta classe:

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;}
}

Como você pode ver no código acima, criei DisplayClasses especiais para minha classe Joint e minha classe CustomObject. No meu projeto, eu tenho muitos, muitos tipos diferentes de objetos que exigem o mesmo tipo de propriedades de classe de exibição sobrepostas.

Acima você pode ver as linhas que adicionei acima das duas últimas propriedades

[TypeConverterAttribute (typeof (ExpandableObjectConverter))]

Esta linha resolve meu problema de exibir o CustomObject como eu quero no propertGrid (quase ... mais sobre isso depois). No entanto, não funciona da mesma maneira para a minha propriedade da Lista Personalizada. Na Lista Personalizada, ela se expande para mostrar apenas Contagem e capacidade (As propriedades reais da Lista) Faz sentido porque isso é, mas não era o que eu queria. Eu queria ver o objeto contido real na lista.

Então aqui está a minha solução complicada, tirada inicialmente deessa questão:

Eu tenho duas classes que estou usando para adicionar dinamicamente objetos à lista de limites de propertyGrid na forma de propriedades. O primeiro (CustomClass) pode serbaixado aqui. Ele é usado para criar propriedades dinamicamente. A segunda classe (DisplayIEnumerable) que estou usando é derivada da primeira e pode ser encontradaAqui.

A classe DisplayIEnumerable percorre os objetos da lista e adiciona uma propriedade a si mesma com as informações contidas em cada objeto. Um DisplayClass é passado para definir exatamente como essas propriedades de objetos devem ser representadas na Grade.

Até este ponto tudo funciona muito bem! como evidenciado por esta imagem (foto não foi criada usando as classes fornecidas, Strings são formatadas de forma diferente nas classes que estou usando, removido o código de formatação para ajudar você a se concentrar no código relevante:

Agora, depois dessa longa intro, a verdadeira questão. Usando as técnicas acima, gostaria de escrever uma classe que possa manipular dinamicamente o CustomObjects para o qual não escrevi classes de exibição exclusivas. Estou pretendendo deixar este código para aqueles que usam o aplicativo para testes, para que possam testar com mais eficiência, sem precisar ter uma classe de exibição completa para cada um dos CustomObjects da minha empresa. (existem centenas) Em vez disso, vinculando o propertyGrid à classe abaixo, espero ter todas as propriedades que são listas e CustomObjects que têm DisplayClasses correspondentes para serem vinculadas em seu lugar.

Aqui está a classe que eu já tentei e tenho um bug com. Eu ainda não tentei implementar a substituição de Lists com minha classe DisplayIEnumerable, mas queria que a funcionalidade básica funcionasse primeiro:

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
   }

Quando executado, o PropertyGrid aparece como deveria:

No entanto, depois de clicar na seta Expand, nada acontece e a seta desaparece:

O que há de errado com a classe acima que não está errado com a minha classe DisplayIEnumerable, que causa essa variação no comportamento?

Eu estou usando a classe DisplayObject assim (dentro de um DisplayClass):

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

Desde já, obrigado! Ficarei muito impressionado se alguém passar por essa questão.

questionAnswers(2)

yourAnswerToTheQuestion