Depuis que j'ai totalement échoué à lire le question pour commencer, voici une nouvelle réponse (c'est un peu un tl; dr, donc vous pouvez toujours passer à la fin et suivez le lien):
Il n'est pas possible d'obtenir la classe de sérialiseur intégrée à travailler parce que vous ne souhaitez pas ajouter les attributs dont il a besoin pour fonctionner. Votre seule option est de sérifier la classe vous-même, cependant, cela ne doit pas être aussi fastidieux que cela puisse paraître; J'ai eu un problème similaire il y a quelques années avec DataGridView en mode virtuel et j'ai produit un virtualiseur générique qui pouvait être utilisé pour virtualiser les données à afficher; il a utilisé un attribut personnalisé:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class showColumnAttribute : System.Attribute
{
///<summary>Optional display format for column</summary>
public string Format;
///<summary>Optional Header string for column<para>Defaults to propety name</para></summary>
public string Title;
///<summary>Optional column edit flag - defaults to false</summary>
public bool ReadOnly;
///<summary>Optional column width</summary>
public int Width;
///<summary>
///Marks public properties that are to be displayed in columns
///</summary>
public showColumnAttribute()
{
Format = String.Empty;
Title = String.Empty;
ReadOnly = false;
Width = 0;
}
}
Et un constructeur:
///<summary>
///Extracts the properties of the supplied type that are to be displayed
///<para>The type must be a class or an InvalidOperationException will be thrown</para>
///</summary>
public Virtualiser(Type t)
{
if (!t.IsClass)
throw new InvalidOperationException("Supplied type is not a class");
List<VirtualColumnInfo> definedColumns = new List<VirtualColumnInfo>();
PropertyInfo[] ps = t.GetProperties();
MethodInfo mg, ms;
for (int i = 0; i < ps.Length; i++)
{
Object[] attr = ps[i].GetCustomAttributes(true);
if (attr.Length > 0)
{
foreach (var a in attr)
{
showColumnAttribute ca = a as showColumnAttribute;
if (ca != null)
{
mg = ps[i].GetGetMethod();
if (mg != null)
{
ms = ps[i].GetSetMethod();
definedColumns.Add
(
new VirtualColumnInfo
(
ps[i].Name, ca.Width, ca.ReadOnly, ca.Title == String.Empty ? ps[i].Name : ca.Title,
ca.Format, mg, ms
)
);
}
break;
}
}
}
}
if (definedColumns.Count > 0)
columns = definedColumns.ToArray();
}
Ceci extrait les propriétés publiques de la classe et des fournitures a marqué des éléments à la DataGridView sous forme de colonnes avec un en-tête, format, etc. L'effet de tout cela (et du reste du code manquant) était que tout type pouvait être virtualisé dans un dataGridView simplement en marquant des propriétés publiques et en appelant le virtualiseur une fois pour un type donné:
#region Virtualisation
static readonly Virtualiser Virtual = new Virtualiser(typeof(UserRecord));
[XmlIgnore] // just in case!
public static int ColumnCount { get { return Virtual.ColumnCount; } }
public static VirtualColumnInfo ColumnInfo(int column)
{
return Virtual.ColumnInfo(column);
}
public Object GetItem(int column)
{
return Virtual.GetItem(column, this);
}
/*
** The supplied item should be a string - it is up to this method to supply a valid value to the property
** setter (this is the simplest place to determine what this is and how it can be derived from a string).
*/
public void SetItem(int column, Object item)
{
String v = item as String;
int t = 0;
if (v == null)
return;
switch (Virtual.GetColumnPropertyName(column))
{
case "DisplayNumber":
if (!int.TryParse(v, out t))
t = 0;
item = t;
break;
}
try
{
Virtual.SetItem(column, this, item);
}
catch { }
}
#endregion
Le nombre de colonnes, leurs propriétés et l'ordre peuvent être spécifiées automatiquement en créant un certain nombre de propriétés publiques dérivées à partir des données de classe:
#region Display columns
[showColumn(ReadOnly = true, Width = 100, Title = "Identification")]
public String DisplayIdent
{
get
{
return ident;
}
set
{
ident = value;
}
}
[showColumn(Width = 70, Title = "Number on Roll")]
public int DisplayNumber
{
get
{
return number;
}
set
{
number = value;
}
}
[showColumn(Width = -100, Title = "Name")]
public string DisplayName
{
get
{
return name == String.Empty ? "??" : name;
}
set
{
name = value;
}
}
#endregion
Ceci virtualiser une classe pour datagridview pour afficher et modifier données et je l'ai utilisé plusieurs fois au cours des années et l'extraction des propriétés à afficher est exactement ce qui est nécessaire pour la sérialisation XML, en effet, il a beaucoup de mêmes caractéristiques.J'allais adapter cette méthode pour faire le même travail pour la sérialisation XML mais quelqu'un l'a déjà fait au https://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=474453, j'espère que vous pourrez utiliser cette méthode pour résoudre votre problème.
1, la sous-classe2 s'étend de la sous-classe 1 2, oui je sais que je peux définir l'élément de tableau en définissant le type dans la classe entité (j'avais mis cela dans la question) la chose est que j'aurai beaucoup de sous classes et ne veulent pas avoir à tout définir dans la classe 'entité'. Je veux le faire automatiquement en fonction d'un attribut ou le type ou quelque chose –
Désolé, typo.The sortie est la même, sauf pour le contenu de l'enregistrement: 20/09/2017 Test1 SubClass1Item>< SubClass2Item> Test2 20/09/2017 01:25:34 SubClass2Item> –
Vous définissez toujours l'élément de tableau et le nom de type dans la classe d'entité. C'est ce que je ne veux pas. J'ai déjà commenté dans l'original. Je veux un moyen de définir tel dans la sous-classe eux-mêmes –