Tambahkan Properti C # secara dinamis saat Runtime

89

Saya tahu ada beberapa pertanyaan yang membahas hal ini, tetapi jawabannya biasanya mengikuti rekomendasi Kamus atau Kumpulan parameter, yang tidak berfungsi dalam situasi saya.

Saya menggunakan perpustakaan yang bekerja melalui refleksi untuk melakukan banyak hal pintar dengan objek dengan properti. Ini berfungsi dengan kelas yang ditentukan, serta kelas dinamis. Saya perlu mengambil satu langkah lebih jauh dan melakukan sesuatu seperti ini:

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;

}

Pustaka berfungsi dengan baik dengan tipe variabel dinamis, dengan properti yang ditetapkan secara manual. Namun saya tidak tahu berapa banyak atau properti apa yang akan ditambahkan sebelumnya.

Paul Grimshaw
sumber

Jawaban:

105

Sudahkah Anda melihat ExpandoObject?

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

Dari MSDN:

Kelas ExpandoObject memungkinkan Anda untuk menambah dan menghapus anggota dari instansnya pada waktu proses dan juga untuk mengatur dan mendapatkan nilai dari anggota ini. Kelas ini mendukung pengikatan dinamis, yang memungkinkan Anda menggunakan sintaks standar seperti sampleObject.sampleMember, bukan sintaks yang lebih kompleks seperti sampleObject.GetAttribute ("sampleMember").

Memungkinkan Anda melakukan hal-hal keren seperti:

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

dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);

Berdasarkan kode Anda yang sebenarnya, Anda mungkin lebih tertarik:

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

Dengan begitu Anda hanya perlu:

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

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

Berasal dari DynamicObject memungkinkan Anda membuat strategi sendiri untuk menangani permintaan anggota dinamis ini, waspadalah ada monster di sini: kompiler tidak akan dapat memverifikasi banyak panggilan dinamis Anda dan Anda tidak akan mendapatkan intellisense, jadi pertahankan itu dalam pikiran.

Clint
sumber
40

Terima kasih @Clint untuk jawaban yang bagus:

Hanya ingin menyoroti betapa mudahnya menyelesaikan ini menggunakan Objek Expando:

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

Anda bisa deserialize string json Anda ke dalam kamus dan kemudian menambahkan properti baru kemudian membuat serial itu.

 var jsonString = @"{}";

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

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

        Console.WriteLine(JsonSerializer.Serialize(jsonDoc));
Khurshid Ali
sumber