Çalışma Zamanında C # Özelliklerini Dinamik Olarak Ekleme


89

Bunu ele alan bazı sorular olduğunu biliyorum, ancak cevaplar genellikle benim durumumda işe yaramayan bir Sözlük veya Parametreler Koleksiyonu önerme çizgisini takip ediyor.

Özelliklere sahip nesnelerle birçok akıllıca şey yapmak için yansıma yoluyla çalışan bir kitaplık kullanıyorum. Bu, tanımlı sınıflarla ve dinamik sınıflarla çalışır. Bunu bir adım daha ileri götürmem ve şu satırlarda bir şeyler yapmam gerekiyor:

public static object GetDynamicObject(Dictionary<string,object> properties) {
    var myObject = new object();
    foreach (var property in properties) {
        //This next line obviously doesn't work... 
        myObject.AddProperty(property.Key,property.Value);
    }
    return myObject;
}

public void Main() {
    var properties = new Dictionary<string,object>();
    properties.Add("Property1",aCustomClassInstance);
    properties.Add("Property2","TestString2");

    var myObject = GetDynamicObject(properties);

    //Then use them like this (or rather the plug in uses them through reflection)
    var customClass = myObject.Property1;
    var myString = myObject.Property2;

}

Kitaplık, manuel olarak atanan özelliklerle dinamik değişken türüyle sorunsuz çalışır. Ancak önceden kaç tane veya hangi özelliklerin ekleneceğini bilmiyorum.

Yanıtlar:


105

ExpandoObject'e bir göz attınız mı?

bkz: http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

MSDN'den:

ExpandoObject sınıfı, örneklerinin üyelerini çalışma zamanında eklemenizi ve silmenizi ve ayrıca bu üyelerin değerlerini ayarlamanızı ve almanızı sağlar. Bu sınıf, sampleObject.GetAttribute ("sampleMember") gibi daha karmaşık sözdizimi yerine sampleObject.sampleMember gibi standart sözdizimini kullanmanızı sağlayan dinamik bağlamayı destekler.

Aşağıdakiler gibi harika şeyler yapmanıza izin verir:

dynamic dynObject = new ExpandoObject();
dynObject.SomeDynamicProperty = "Hello!";
dynObject.SomeDynamicAction = (msg) =>
    {
        Console.WriteLine(msg);
    };

dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);

Gerçek kodunuza bağlı olarak şunlarla daha fazla ilgilenebilirsiniz:

public static dynamic GetDynamicObject(Dictionary<string, object> properties)
{
    return new MyDynObject(properties);
}

public sealed class MyDynObject : DynamicObject
{
    private readonly Dictionary<string, object> _properties;

    public MyDynObject(Dictionary<string, object> properties)
    {
        _properties = properties;
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return _properties.Keys;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (_properties.ContainsKey(binder.Name))
        {
            result = _properties[binder.Name];
            return true;
        }
        else
        {
            result = null;
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (_properties.ContainsKey(binder.Name))
        {
            _properties[binder.Name] = value;
            return true;
        }
        else
        {
            return false;
        }
    }
}

Bu şekilde ihtiyacınız olan şey:

var dyn = GetDynamicObject(new Dictionary<string, object>()
    {
        {"prop1", 12},
    });

Console.WriteLine(dyn.prop1);
dyn.prop1 = 150;

DynamicObject yola çıkarak size, bu dinamik üyesi istekleri işlemek için kendi stratejisi ile gelip verir : burada orada dikkat canavarlar derleyici olacak değil dinamik bir çok görüşme doğrulayamazsınız ve intellisense almazsınız, bu yüzden sadece tutmak bunu akılda tutun.


40

Harika cevap için teşekkürler @Clint:

Bunu Expando Nesnesini kullanarak çözmenin ne kadar kolay olduğunu vurgulamak istedim:

    var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
    foreach (var property in properties) {
        dynamicObject.Add(property.Key,property.Value);
    }

4

json dizenizin serisini kaldırıp bir sözlüğe dönüştürebilir ve ardından yeni özellikler ekleyebilir ve ardından onu serileştirebilirsiniz.

 var jsonString = @"{}";

        var jsonDoc = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);

        jsonDoc.Add("Name", "Khurshid Ali");

        Console.WriteLine(JsonSerializer.Serialize(jsonDoc));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.