2 Stimmen

Filtern der Eigenschaften eines Objekts nach Name

Ich führe eine einfache Validierung verschiedener Typen durch. Der aktuelle Test, an dem ich arbeite, überprüft, ob ihre Eigenschaften ausgefüllt sind. In diesem Fall ist "gefüllt" definiert als "nicht null", "eine Länge größer als null" (bei einer Zeichenkette) oder "ungleich 0" (bei einer Ganzzahl).

Der "heikle" Teil dieses Tests besteht darin, dass einige Eigenschaften gegen diese Prüfung immun sind. Im Moment verwende ich eine riesige if-Anweisung, die Eigenschaften ausschließt, die nicht geprüft werden müssen.

//Gets all the properties of the currect feature.
System.Reflection.PropertyInfo[] pi = t.GetProperties();

for(int i = 0; i < pi.Length; i++)
{
    if(!pi[i].Name.Equals("PropertyOne") 
    && !pi[i].Name.Equals("PropertyTwo") 
    && !pi[i].Name.Equals("PropertyThree") 
            //... repeat a bunch more times
    && !pi[i].Name.IndexOf("ValueOne") != -1 
    && !pi[i].Name.IndexOf("ValueTwo") != -1 
            //... repeat a bunch more times
    {
        //Perform the validation check.
    }                 
}

Bei der Profilerstellung bemerkte ich, dass die if-Anweisung tatsächlich schlechter als die Reflexion durchgeführt wird (nicht, dass die Reflexion blitzschnell ist). Gibt es einen effizienteren Weg, um die Eigenschaften von mehreren verschiedenen Typen zu filtern?

Ich habe über eine massive regulären Ausdruck gedacht, aber ich bin unsicher, wie es zu formatieren, plus es wäre wahrscheinlich unlesbar angesichts seiner Größe. Ich habe auch in Betracht gezogen, die Werte in einer Liste zu speichern und dann mit Linq, aber ich bin nicht sicher, wie die Fälle zu behandeln, die String.IndexOf() verwenden, um zu finden, wenn die Eigenschaft einen bestimmten Wert enthält.

Vielen Dank im Voraus.

3voto

Jon Skeet Punkte 1325502

Erstellen Sie ein HashSet "exactNames" mit PropertyOne, PropertyTwo usw., und dann eine Liste "partialNames" mit ValueOne, ValueTwo usw. Dann:

var matchingProperties = pi.Where(exactNames.Contains(pi.Name) ||
                          partialNames.Any(name => pi.Name.Contains(name));

foreach (PropertyInfo property in matchingProperties)
{
    // Stuff
}

(Ungewöhnliche Einrückung, um einen Umbruch zu vermeiden.)

Beachten Sie, dass Sie die Menge der zu überprüfenden Eigenschaften für jeden Typ zwischenlagern können, so dass Sie diese Prüfung nur einmal pro Typ durchführen müssen.

0voto

spasarto Punkte 259

Ihre Idee hat mir geholfen, mein Programm zu beschleunigen, vielen Dank. Allerdings hatten Sie einige syntaktische Probleme, und Sie glichen Elemente in den Listen ab, während ich Elemente benötigte, die nicht in der Liste waren. Hier ist der Code, den ich am Ende verwendet habe.

List<System.Reflection.PropertyInfo> pi = type.GetProperties().ToList();

var matchingProperties = pi.Where( prop => !PropertyExclusionSet.Contains( prop.Name )
&& !PropertiesPartialSet.Any( name => prop.Name.Contains( name ) ) );

0voto

Ted Elliott Punkte 3118

Sie könnten Ihre Eigenschaften mit Attributen ausstatten, die angeben, welche Aktion mit ihnen durchgeführt werden muss.

public class MyClass {

   [CheckMe]
   public int PropertyOne { get; set; }

   [DontCheckMe]
   public int PropertyTwo { get; set; }

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X