Добавление неизвестных (во время разработки) свойств в ExpandoObject

просто исследуя С# 4. Попытка разобраться во всех этих динамических материалах. Извините, если этот вопрос глупый, нет опыта в этом домене.

Если у меня есть ExpandoObject и вы хотите добавить общедоступные свойства (с get и set) к нему во время выполнения, как бы я это сделал?

Например, у меня есть documentTemplate и документ, который имеет свойство, указывающее на documentTemplate. Этот документTemplate имеет несколько названий тегов (например, возможности, разработанные среди студентов), которые следует решать при создании документа (например, Концентрация, память и т.д.). Поэтому, как только шаблон установлен в документе, я хочу создать класс, который имеет свойства с теми же именами, что и названия тегов в шаблоне, а затем с помощью некоторого элемента пользовательского интерфейса, такого как PropertyGrid, я могу иметь пользователя введите значения тегов в заголовки тегов.

Спасибо за чтение!

Ответ 1

Я задавался вопросом, как можно было бы добавить участников в класс "на лету" и придумал этот пример:

using System;
using System.Collections.Generic;
using System.Dynamic;

class Program
{
    static void Main()
    {
        dynamic expando = new ExpandoObject();
        var p = expando as IDictionary<String, object>;

        p["A"] = "New val 1";
        p["B"] = "New val 2";

        Console.WriteLine(expando.A);
        Console.WriteLine(expando.B);
    }
}

Точка этого фрагмента кода состоит в том, что члены A и B определены как строковые литералы (жестко закодированные/строковые) и добавлены через интерфейс ExpandoObject IDictionary. Мы проверяем существование и значения ключей (и доказываем концепцию), обращаясь к ним напрямую и выводя на консоль.

Ответ 2

Можно добавить свойства делегата в ExpandoObject, которые затем действуют (почти) точно так же, как методы. например.

dynamic obj = new ExpandoObject();
obj.GetDocumentTemplate = () => { ... };
...
obj.GetDocumentTemplate(); // invokes delegate

Ответ 3

Да, ExpandoObject очень удобен для динамического добавления свойств в "пакет свойств". Однако представление о предоставлении такого свойства геттер и сеттер не поддерживается. Возможно, это ясно, если вы подумаете об этом немного: это не будет динамическим свойством, если вы уже знаете, что должны делать геттер и сеттер. Самое близкое, что вы можете получить, - это реализовать событие INotifyPropertyChanged, чтобы вы могли обнаружить изменения. Пример кода:

using System;
using System.Dynamic;
using System.ComponentModel;

class Program {
  static void Main(string[] args) {
    dynamic obj = new ExpandoObject();
    obj.test = 42;     // Add a property
    Console.WriteLine(obj.test);

    var inpc = (INotifyPropertyChanged)obj;
    inpc.PropertyChanged += inpc_PropertyChanged;
    obj.test = "foo";
    Console.ReadLine();
  }

  static void inpc_PropertyChanged(object sender, PropertyChangedEventArgs e) {
    Console.WriteLine("'{0}' property changed", e.PropertyName);
  }

}

Ответ 4

Ответы до сих пор хорошо освещают основы, но я чувствовал, что статья MSDN Magazine также стоит того, чтобы поделиться:

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

Он описывает некоторые примеры использования динамического ввода XML для динамического создания и использования ExpandoObjects.

Ответ 5

Я только что обнаружил этот интересный факт: Привязки XAML к ExpandoObject также создадут свойства, к которым пытается привязать привязка.

Мне все еще нужно больше творчества, чтобы узнать, для чего это может быть полезно. Создание динамического объекта в пользовательском интерфейсе? звучит круто: D Я попробую что-нибудь.