75 votes

C #: Comment obtenir toutes les propriétés de chaîne publiques (à la fois get et set) d'un type

Je suis en train de faire une méthode qui vous permettra de parcourir une liste de génériques d'objets et de remplacer toutes leurs propriétés de type string soit null vide ou avec un remplacement.

Comment est une bonne façon de le faire?

J'ai ce genre de... coque... pour l'instant:

public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    var properties = typeof(T).GetProperties( -- What BindingFlags? -- );

    foreach(var p in properties)
    {
        foreach(var item in list)
        {
            if(string.IsNullOrEmpty((string) p.GetValue(item, null)))
                p.SetValue(item, replacement, null);
        }
    }
}

Alors, comment puis-je trouver toutes les propriétés d'un type qui sont:

  • De type string
  • A public get
  • A public set

    ?


J'ai fait cette classe de test:

class TestSubject
{
    public string Public;
    private string Private;

    public string PublicPublic { get; set; }
    public string PublicPrivate { get; private set; }
    public string PrivatePublic { private get; set; }
    private string PrivatePrivate { get; set; }
}

Le code suivant ne fonctionne pas:

var properties = typeof(TestSubject)
        .GetProperties(BindingFlags.Instance|BindingFlags.Public)
        .Where(ø => ø.CanRead && ø.CanWrite)
        .Where(ø => ø.PropertyType == typeof(string));

Si j'ai imprimer le Nom de ces propriétés, j'y arrive, j'obtiens:

PublicPublic Public-privé PrivatePublic

En d'autres termes, je reçois deux propriétés de trop.


Remarque: Cela pourrait être fait dans une meilleure façon... en utilisant foreach imbriquée et la réflexion, et tous ici... mais si vous avez une excellente alternative idées, s'il vous plaît laissez-moi savoir parce que je veux apprendre!

121voto

Colin Burnett Points 4572

Votre code réécrit. N'utilise ni LINQ ni var.

 public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo p in properties)
    {
        // Only work with strings
        if (p.PropertyType != typeof(string)) { continue; }

        // If not writable then cannot null it; if not readable then cannot check it's value
        if (!p.CanWrite || !p.CanRead) { continue; }

        MethodInfo mget = p.GetGetMethod(false);
        MethodInfo mset = p.GetSetMethod(false);

        // Get and set methods have to be public
        if (mget == null) { continue; }
        if (mset == null) { continue; }

        foreach (T item in list)
        {
            if (string.IsNullOrEmpty((string)p.GetValue(item, null)))
            {
                p.SetValue(item, replacement, null);
            }
        }
    }
}
 

16voto

Fredrik Mörk Points 85694

Vous trouverez les propriétés comme tels, en BindingFlags.Public | BindingFlags.Instance. Ensuite, vous aurez besoin d'examiner chaque PropertyInfo exemple en cochant la CanWrite et CanRead propriétés, afin de savoir s'ils sont lisibles et/ou en écriture.

Mise à jour: exemple de code

PropertyInfo[] props = yourClassInstance.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < props.Length; i++)
{
    if (props[i].PropertyType == typeof(string) && props[i].CanWrite)
    {
        // do your update
    }
}


J'ai regardé plus en détail après votre mise à jour. Si vous examinez également le MethodInfo les objets retournés par GetGetMethod et GetSetMethod vous touchez la cible, je pense;

 var properties = typeof(TestSubject).GetProperties(BindingFlags.Instance | BindingFlags.Public)
        .Where(ø => ø.CanRead && ø.CanWrite)
        .Where(ø => ø.PropertyType == typeof(string))
        .Where(ø => ø.GetGetMethod(true).IsPublic)
        .Where(ø => ø.GetSetMethod(true).IsPublic);

Par défaut, ces deux méthodes retournent seuls les getters et les setters (de risquer une NullReferenceException dans un cas de ce genre), mais en passant true comme ci-dessus rend également le retour de celles du secteur privé. Ensuite, vous pouvez examiner l' IsPublic (ou IsPrivate) propriétés.

1voto

tvanfosson Points 268301

Si vous ne spécifiez aucun indicateur de liaison, vous obtiendrez les propriétés d'instance publiques, ce que vous souhaitez. Mais vous devrez ensuite vérifier si le PropertyType de l'objet PropertyInfo est de type String. Sauf si vous le savez à l'avance, vous devrez également vérifier si la propriété est lisible / inscriptible, comme l'indique @Fredrik.

 using System.Linq;

public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    var properties = typeof(T).GetProperties()
                              .Where( p => p.PropertyType == typeof(string) );
    foreach(var p in properties)
    {
        foreach(var item in list)
        {
            if(string.IsNullOrEmpty((string) p.GetValue(item, null)))
                p.SetValue(item, replacement, null);
        }
    }
}
 

1voto

jeffery Points 11

Bonjour, vous pouvez vous référer à http://jefferytay.wordpress.com/2010/05/03/simple-and-useful-tostring/

pour une méthode de substitution tostring qui vous permet d'obtenir toutes les propriétés de la classe

0voto

ba__friend Points 3306

BindingFlags.Public | BindingFlags.Instance devrait le faire

GetSetMethod ()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X