Добавление неизвестных (во время разработки) свойств в ExpandoObject - PullRequest
48 голосов
/ 04 июня 2010

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

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

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

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

Ответы [ 5 ]

94 голосов
/ 22 августа 2010

Я подумал, как можно добавить членов в класс "на лету", и предложил следующий пример:

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 определены как строковые литералы (жестко запрограммированные / строковые) и добавляются через интерфейс IDictionary ExpandoObject. Мы проверяем наличие и значения ключей (и подтверждаем концепцию), напрямую обращаясь к ним и выводя их на консоль.

4 голосов
/ 04 июня 2010

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

dynamic obj = new ExpandoObject();
obj.GetDocumentTemplate = () => { ... };
...
obj.GetDocumentTemplate(); // invokes delegate
3 голосов
/ 04 июня 2010

Да, 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);
  }

}
2 голосов
/ 04 августа 2011

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

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

2 голосов
/ 04 ноября 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...