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>

1voto

Domysee Punkte 12280

jheddings et AlexD haben beide hervorragende Antworten auf die Lösung von Property Strings geschrieben. Ich möchte meine in den Mix zu werfen, da ich eine spezielle Bibliothek genau für diesen Zweck geschrieben.

Pather.CSharp Die Hauptklasse von Resolver . Standardmäßig kann es Eigenschaften, Array- und Wörterbucheinträge auflösen.

Wenn Sie also zum Beispiel ein Objekt wie dieses haben

var o = new { Property1 = new { Property2 = "value" } };

und wollen sich Property2 können Sie wie folgt vorgehen:

IResolver resolver = new Resolver();
var path = "Property1.Property2";
object result = r.Resolve(o, path); 
//=> "value"

Dies ist das einfachste Beispiel für die Pfade, die es auflösen kann. Wenn Sie sehen wollen, was es sonst noch kann, oder wie Sie es erweitern können, gehen Sie einfach zu seiner Github-Seite .

1voto

Jeff Codes Punkte 67

Hier ist, was ich auf der Grundlage anderer Antworten erhalten habe. Ein wenig overkill auf immer so spezifisch mit der Fehlerbehandlung.

public static T GetPropertyValue<T>(object sourceInstance, string targetPropertyName, bool throwExceptionIfNotExists = false)
{
    string errorMsg = null;

    try
    {
        if (sourceInstance == null || string.IsNullOrWhiteSpace(targetPropertyName))
        {
            errorMsg = $"Source object is null or property name is null or whitespace. '{targetPropertyName}'";
            Log.Warn(errorMsg);

            if (throwExceptionIfNotExists)
                throw new ArgumentException(errorMsg);
            else
                return default(T);
        }

        Type returnType = typeof(T);
        Type sourceType = sourceInstance.GetType();

        PropertyInfo propertyInfo = sourceType.GetProperty(targetPropertyName, returnType);
        if (propertyInfo == null)
        {
            errorMsg = $"Property name '{targetPropertyName}' of type '{returnType}' not found for source object of type '{sourceType}'";
            Log.Warn(errorMsg);

            if (throwExceptionIfNotExists)
                throw new ArgumentException(errorMsg);
            else
                return default(T);
        }

        return (T)propertyInfo.GetValue(sourceInstance, null);
    }
    catch(Exception ex)
    {
        errorMsg = $"Problem getting property name '{targetPropertyName}' from source instance.";
        Log.Error(errorMsg, ex);

        if (throwExceptionIfNotExists)
            throw;
    }

    return default(T);
}

0voto

user3175253 Punkte 558

Hier ist meine Lösung. Sie funktioniert auch mit COM-Objekten und ermöglicht den Zugriff auf Auflistungs-/Array-Elemente aus COM-Objekten.

public static object GetPropValue(this object obj, string name)
{
    foreach (string part in name.Split('.'))
    {
        if (obj == null) { return null; }

        Type type = obj.GetType();
        if (type.Name == "__ComObject")
        {
            if (part.Contains('['))
            {
                string partWithoundIndex = part;
                int index = ParseIndexFromPropertyName(ref partWithoundIndex);
                obj = Versioned.CallByName(obj, partWithoundIndex, CallType.Get, index);
            }
            else
            {
                obj = Versioned.CallByName(obj, part, CallType.Get);
            }
        }
        else
        {
            PropertyInfo info = type.GetProperty(part);
            if (info == null) { return null; }
            obj = info.GetValue(obj, null);
        }
    }
    return obj;
}

private static int ParseIndexFromPropertyName(ref string name)
{
    int index = -1;
    int s = name.IndexOf('[') + 1;
    int e = name.IndexOf(']');
    if (e < s)
    {
        throw new ArgumentException();
    }
    string tmp = name.Substring(s, e - s);
    index = Convert.ToInt32(tmp);
    name = name.Substring(0, s - 1);
    return index;
}

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