1210 Stimmen

Abrufen des Eigenschaftswerts aus einer Zeichenkette mittels Reflexion

Ich versuche die Implementierung der Datentransformation mit Reflection 1 Beispiel in meinem Code.

Le site GetSourceValue Funktion hat einen Schalter, der verschiedene Typen vergleicht, aber ich möchte diese Typen und Eigenschaften entfernen und die GetSourceValue den Wert der Eigenschaft mit nur einer einzigen Zeichenkette als Parameter abrufen. Ich möchte eine Klasse und eine Eigenschaft in der Zeichenfolge übergeben und den Wert der Eigenschaft auflösen.

Ist dies möglich?

1 <a href="https://web.archive.org/web/20130815002453/http://msmvps.com/blogs/shahed/archive/2008/07/24/c-reflection-tips-data-transformation-using-reflection.aspx" rel="noreferrer">Webarchiv-Version des ursprünglichen Blogbeitrags</a>

2voto

Kyle Punkte 29
Dim NewHandle As YourType = CType(Microsoft.VisualBasic.CallByName(ObjectThatContainsYourVariable, "YourVariableName", CallType), YourType)

2voto

Guvante Punkte 18175

Sie erwähnen nie, welches Objekt Sie untersuchen, und da Sie diejenigen ablehnen, die auf ein bestimmtes Objekt verweisen, gehe ich davon aus, dass Sie ein statisches Objekt meinen.

using System.Reflection;
public object GetPropValue(string prop)
{
    int splitPoint = prop.LastIndexOf('.');
    Type type = Assembly.GetEntryAssembly().GetType(prop.Substring(0, splitPoint));
    object obj = null;
    return type.GetProperty(prop.Substring(splitPoint + 1)).GetValue(obj, null);
}

Beachten Sie, dass ich das zu prüfende Objekt mit der lokalen Variable obj . null bedeutet statisch, andernfalls setzen Sie ihn auf den von Ihnen gewünschten Wert. Beachten Sie auch, dass die GetEntryAssembly() ist eine der wenigen verfügbaren Methoden, um die "laufende" Baugruppe zu erhalten. Vielleicht möchten Sie damit herumspielen, wenn Sie Schwierigkeiten beim Laden des Typs haben.

2voto

Werfen Sie einen Blick auf die Heleonix.Reflexion Bibliothek. Sie können Mitglieder über Pfade erhalten/setzen/aufrufen oder einen Getter/Setter (Lambda, das in einen Delegaten kompiliert wird) erstellen, was schneller ist als Reflection. Zum Beispiel:

var success = Reflector.Get(DateTime.Now, null, "Date.Year", out int value);

Oder erstellen Sie einen Getter einmal und Zwischenspeicher für die Wiederverwendung (dies ist leistungsfähiger, aber könnte NullReferenceException auslösen, wenn ein Zwischenelement null ist):

var getter = Reflector.CreateGetter<DateTime, int>("Date.Year", typeof(DateTime));
getter(DateTime.Now);

Oder wenn Sie eine List<Action<object, object>> von verschiedenen Gettern, geben Sie einfach Basistypen für kompilierte Delegierte an (Typkonvertierungen werden in kompilierte Lambdas eingefügt):

var getter = Reflector.CreateGetter<object, object>("Date.Year", typeof(DateTime));
getter(DateTime.Now);

1 Stimmen

Verwenden Sie niemals Bibliotheken von Drittanbietern, wenn Sie sie in Ihrem eigenen Code in angemessener Zeit in 5-10 Zeilen implementieren können.

2voto

pasx Punkte 2222

Obwohl die ursprüngliche Frage lautete, wie man den Wert der Eigenschaft mit nur einer Zeichenkette als Parameter abrufen ist es hier sehr sinnvoll, einen Ausdruck und nicht nur eine Zeichenkette zu verwenden, um sicherzustellen, dass der Aufrufer niemals einen hart kodierten Eigenschaftsnamen verwendet. Hier ist eine einzeilige Version mit Verwendung:

public static class Utils
...
    public static TVal GetPropertyValue<T, TVal>(T t, Expression<Func<T, TVal>> x)
        => (TVal)((x.Body as MemberExpression)?.Member as PropertyInfo)!.GetValue(t);

...
    var val = Utils.GetPropertyValue(foo,  p => p.Bar);

Hier ist eine etwas bessere Version im Hinblick auf die Lesbarkeit und Fehlerbehandlung:

public static TVal GetPropertyValue<T, TVal>(T t, Expression<Func<T, TVal>> x)
{
    var m = (x.Body as MemberExpression)?.Member
    var p = m as PropertyInfo;

    if (null == p)
        throw new ArgumentException($"Unknown property: {typeof(T).Name}.{(m?.Name??"???")}");

    return (TVal)p.GetValue(t);
}

Kurz gesagt, Sie geben einen Lambda-Ausdruck ein, der eine Eigenschaft ausliest. Der Körper des Lambda-Ausdrucks - der Teil rechts vom fetten Pfeil - ist ein Member-Ausdruck, aus dem Sie den Member-Namen erhalten und den Sie in eine PropertyInfo umwandeln können, vorausgesetzt, der Member ist tatsächlich eine Property und nicht etwa eine Methode.

In der Kurzfassung sagt der null-vergebende Operator - das ! im Ausdruck - dem Compiler, dass die PropertyInfo nicht null sein wird. Dies ist eine große Lüge und Sie erhalten zur Laufzeit eine NullReferenceException. Die längere Version gibt Ihnen den Namen der Eigenschaft, wenn sie es schafft, ihn zu erhalten.

PS: Dank an Oleg G. für die erste Version dieses Codes :)

0 Stimmen

Fehlendes Semikolon bei var m = Linie?

1voto

Budiantowang Punkte 11

Kürzerer Weg ....

var a = new Test { Id = 1 , Name = "A" , date = DateTime.Now};
var b = new Test { Id = 1 , Name = "AXXX", date = DateTime.Now };

var compare = string.Join("",a.GetType().GetProperties().Select(x => x.GetValue(a)).ToArray())==
              string.Join("",b.GetType().GetProperties().Select(x => x.GetValue(b)).ToArray());

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