Динамічно додавати властивості C # під час виконання


89

Я знаю, що є кілька питань, які стосуються цього, але відповіді, як правило, слідують за рекомендацією словника або збірника параметрів, що не працює в моїй ситуації.

Я використовую бібліотеку, яка працює за допомогою роздумів, щоб робити багато розумних речей з об’єктами з властивостями. Це працює з визначеними класами, а також динамічними класами. Мені потрібно зробити цей крок далі і зробити щось подібне:

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;

}

Бібліотека чудово працює з динамічним типом змінних, із властивостями, призначеними вручну. Однак я не знаю, скільки або яких властивостей буде додано заздалегідь.

Відповіді:


105

Ви заглянули в ExpandoObject?

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

З MSDN:

Клас ExpandoObject дозволяє додавати та видаляти члени його екземплярів під час виконання, а також встановлювати та отримувати значення цих членів. Цей клас підтримує динамічне прив'язку, що дозволяє використовувати стандартний синтаксис, такий як sampleObject.sampleMember замість більш складного синтаксису, як sampleObject.GetAttribute ("sampleMember").

Дозволяючи вам робити круті речі, такі як:

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

dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);

На основі вашого фактичного коду вас може зацікавити:

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

Таким чином вам просто потрібно:

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

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

Виведення з DynamicObject дозволяє вам розробити власну стратегію для обробки цих динамічних запитів членів, остерігайтеся, щоб тут були монстри: компілятор не зможе перевірити велику кількість ваших динамічних викликів, і ви не отримаєте intellisense, тому просто продовжуйте це на увазі.


39

Дякую @Clint за чудову відповідь:

Просто хотів підкреслити, як легко було це вирішити за допомогою об’єкта Expando:

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

3

ви можете десеріалізувати рядок json у словник, а потім додати нові властивості, а потім серіалізувати його.

 var jsonString = @"{}";

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

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

        Console.WriteLine(JsonSerializer.Serialize(jsonDoc));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.