example - c# xml documentation



Zugreifen auf die Objekteigenschaft als Zeichenfolge und Festlegen ihres Werts (6)

Ich bin mit den vorherigen Postern einverstanden, dass Sie wahrscheinlich die Eigenschaften verwenden müssen. Die Reflexion ist sehr langsam im Vergleich zum direkten Zugriff auf das Eigentum.

Wenn Sie dagegen eine Liste benutzerdefinierter Eigenschaften verwalten müssen, können Sie keine C # -Eigenschaften verwenden. Sie müssen so tun, als wären Sie ein Dictionary , oder Sie müssen eine Eigenschaft verfügbar machen, die sich wie ein Dictionary verhält. Im Folgenden finden Sie ein Beispiel dafür, wie Sie festlegen können, dass die Account-Klasse benutzerdefinierte Eigenschaften unterstützt:

public class Account
{
    Dictionary<string, object> properties;
    public object this[string propertyName]
    {
        get
        {
            if (properties.ContainsKey[propertyName])
                return properties[propertyName];
            else
                return null;
        }
        set
        {
            properties[propertyName] = value;
        }
    }
}

Ich habe eine Instanz der Account Klasse. Jedes Kontoobjekt hat einen Eigentümer, eine Referenz usw.

Ein Weg, wie ich auf die Eigenschaften eines Kontos zugreifen kann, ist über Accessoren wie

account.Reference;

aber ich möchte in der Lage sein, mit dynamischen String-Selektoren darauf zuzugreifen, wie:

account["PropertyName"];

genau wie in JavaScript. Ich hätte also ein account["Reference"] das den Wert zurückgibt, aber ich möchte auch in der Lage sein, danach einen neuen Wert wie folgt zuzuweisen:

account["Reference"] = "124ds4EE2s";

Mir ist aufgefallen, dass ich es gebrauchen kann

DataBinder.Eval(account,"Reference") 

um eine Eigenschaft basierend auf einer Zeichenfolge zu erhalten, aber mit dieser kann ich der Eigenschaft keinen Wert zuweisen.

Irgendeine Idee, wie ich das machen könnte?


Answer #1

Ich habe die Reflektionsmethode von Richard verwendet, aber die Mengenmethode ausgearbeitet, um andere Typen wie Zeichenfolgen und Nullen zu behandeln.

public object this[string propertyName]
{
    get
    {
        PropertyInfo property = GetType().GetProperty(propertyName);
        return property.GetValue(this, null);
    }
    set
    {
        PropertyInfo property = GetType().GetProperty(propertyName);
        Type propType = property.PropertyType;
        if (value == null)
        {
            if (propType.IsValueType && Nullable.GetUnderlyingType(propType) == null)
            {
                throw new InvalidCastException();
            }
            else
            {
                property.SetValue(this, null, null);
            }
        }
        else if (value.GetType() == propType)
        {
            property.SetValue(this, value, null);
        }
        else
        {
            TypeConverter typeConverter = TypeDescriptor.GetConverter(propType);
            object propValue = typeConverter.ConvertFromString(value.ToString());
            property.SetValue(this, propValue, null);
        }
    }
}

Die Funktion SetValue () löst einen Fehler aus, wenn die Konvertierung nicht funktioniert.


Answer #2

Sie könnten versuchen, den Indexer mit Reflektion zu kombinieren ...

public object this[string propertyName]
{
    get
    {
        PropertyInfo property = GetType().GetProperty(propertyName);
        return property.GetValue(this, null);
    }
    set
    {
        PropertyInfo property = GetType().GetProperty(propertyName);
        property.SetValue(this,value, null);
    }
}

Answer #3

Sie müssen Reflection verwenden:

PropertyInfo property = typeof(Account).GetProperty("Reference");

property.SetValue(myAccount, "...", null);

Beachten Sie, dass dies sehr langsam sein wird.


Answer #4

Wenn es sich um Ihre eigenen Objekte handelt, können Sie einen Indexer für den Zugriff auf die Felder bereitstellen. Ich kann das nicht wirklich empfehlen, aber es würde dir erlauben, was du willst.

public object this[string propertyName]
{
    get
    {
        if(propertyName == "Reference")
            return this.Reference;
        else
            return null;
    }
    set
    {
        if(propertyName == "Reference")
            this.Reference = value;
        else
            // do error case here            
    }
}

Beachten Sie, dass Sie dadurch die Typensicherheit verlieren.


Answer #5

Zuallererst sollten Sie vermeiden, dies zu verwenden; C # ist eine stark typisierte Sprache. Profitieren Sie daher von den damit verbundenen Vorteilen in Bezug auf Typensicherheit und Leistung.

Wenn Sie einen berechtigten Grund haben, den Wert einer Eigenschaft dynamisch abzurufen und festzulegen (dh wenn Typ und / oder Eigenschaftsname im Code nicht definiert werden können), müssen Sie Reflection verwenden.

Der am meisten inline aussehende Weg wäre:

object value = typeof(YourType).GetProperty("PropertyName").GetValue(yourInstance);
...
typeof(YourType).GetProperty("PropertyName").SetValue(yourInstance, "value");

Sie können das PropertyInfo Objekt jedoch zwischenspeichern, um es lesbarer zu machen:

System.Reflection.PropertyInfo prop = typeof(YourType).GetProperty("PropertyName");

object value = prop.GetValue(yourInstance);
...
prop.SetValue(yourInstance, "value");




databinder