Soru Object özelliğine string olarak erişme ve değerini ayarlama


Bir örneğim var Account sınıf. Her hesap nesnesinin bir sahibi, referansı vb.

Hesap özelliklerine erişebilmemin bir yolu,

account.Reference;

ama ben gibi dinamik dize seçiciler kullanarak erişebilmek istiyorum:

account["PropertyName"];

tıpkı JavaScript’te olduğu gibi. Yani ben olurdu account["Reference"] Bu, değeri geri döndürecek, ama aynı zamanda bundan sonra yeni bir değer atayabilmeyi istiyorum:

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

Kullanabileceğimi fark ettim

DataBinder.Eval(account,"Reference") 

Bir dizeye dayalı bir özellik almak için, ancak bunu kullanarak mülke bir değer atayamıyorum.

Bunu nasıl yapabileceğime dair bir fikrin var mı?


30
2018-05-25 13:44


Menşei


"C #" demek istiyorsun, değil mi "csharp"? - John Saunders
C # bir betik dili değil; genellikle yeni bir dil öğrenirken; Onunla birlikte gelen yeni deyimler ve konvansiyonları öğrenmeniz gerekecek. - Pierreten


Cevaplar:


Her şeyden önce, bunu kullanmaktan kaçınmalısınız; C # güçlü bir şekilde yazılmış bir dildir, bu nedenle bu yöndeki eşlik eden güvenlik ve performans avantajlarından yararlanın.

Bir özelliğin değerini dinamik olarak almak ve ayarlamak için geçerli bir nedeniniz varsa (başka bir deyişle, kodda tür ve / veya özellik adı tanımlanamıyorsa), yansıma kullanmanız gerekir.

En satır içi yol bu olurdu:

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

Ancak, PropertyInfo nesne daha okunabilir hale getirmek için:

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

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

44
2018-05-25 13:47



Birisi bana C # 'un çok güçlü bir şekilde yazıldığını söyledi. Biraz düşünmeden sonra, o kadar da kötü olmadığına karar verdim. - deed02392
Kalıcılık için bunu kullanarak çok fazla kodlama (ve daha az kod = daha az hata) kaydedebilirsiniz. Yakut gibi kullanın ve db tablonuzun özelliklerle eşleşmesini sağlayın ve sonsuz yazmaya (hem güçlü hem de klavye) değil, algoritmalara odaklanın - Garr Godfrey
@ deed02392 Güçlü yazılmıştır, ancak Statik-Yazılansorun burada. - Florian
@Florian benim şaka :-) cevapsız - deed02392
@ deed02392 lanet, şimdi açık görünüyor! yeterli değil yansıma yorum yapmadan önce. - Florian


Dizinleyiciyi yansıtma ile birleştirmeyi deneyebilirsiniz ...

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);
    }
}

24
2018-05-25 15:20



İyi iş.Bu bana çok yardımcı oldu - sudhAnsu63
+1 Benim için de çalışıyor. Mülkün muhtemelen boş olma özelliğini kullanmanız gerektiğini unutmayın. - Will Bickford


Kendi nesnelerinizse, alanlara erişmek için bir dizinleyici sağlayabilirsiniz. Bunu gerçekten önermiyorum ama ne istediğine izin verecekti.

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            
    }
}

Bunu yaparken güvenliğini kaybettiğinizi unutmayın.


4
2018-05-25 13:56





Richard'dan yansıma yöntemini kullandım, ancak dizeler ve boş karakterler gibi kullanılan diğer türleri işlemek için set yöntemini ayrıntılandırdım.

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);
        }
    }
}

Dönüştürme çalışmazsa SetValue () işlevi bir hata verir.


4
2018-01-12 05:36





.Net 4 kullanıyorsanız, şimdi dinamik anahtar kelimeyi kullanabilirsiniz.

dynamic foo = account;
foo.Reference = "124ds4EE2s";

3
2017-09-04 10:29





Reflection kullanmanız gerekiyor:

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

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

Bunun çok yavaş olacağını unutmayın.


1
2018-05-25 13:48





Önceki posterlere katılıyorum, muhtemelen özellikleri kullanmanız gerekiyor. Yansıma, doğrudan mülk erişimine kıyasla çok yavaştır.

Öte yandan, kullanıcı tanımlı özelliklerin bir listesini tutmanız gerekiyorsa, C # özelliklerini kullanamazsınız. Sen bir numarasın gibi davranmalısın Dictionaryya da gibi davranan bir özelliği açığa çıkarmanız gerekir. Dictionary. Hesap sınıfı desteğini kullanıcı tanımlı özelliklerde nasıl yapabileceğinize ilişkin bir örnek:

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;
        }
    }
}

1
2018-05-25 14:03





Kişisel olarak uzantı yöntemleriyle çalışmayı tercih ediyorum, bu yüzden benim kodum:

public static class ReflectionExtensions
{
    public static void SetPropertyValue(this object Target,
        string PropertyName,
        object NewValue)
    {
        if (Target == null) return; //or throw exception

        System.Reflection.PropertyInfo prop = Target.GetType().GetProperty(PropertyName);

        if (prop == null) return; //or throw exception

        object value = prop.GetValue(Target, null);

        prop.SetValue(Target, NewValue, null);
    }
}

1
2017-10-03 13:40