Как создать значимое динамическое свойство? - PullRequest
3 голосов
/ 14 марта 2010

Вымышленный пример здесь. Предположим, я разработал класс с именем IODevice. Этот класс уже реализует структуру, которая позволяет мне использовать ее следующим образом:

        IODevice dio = new IODevice();

        try
        {
            dio.Pin["IsBirdInCageSensor"].Set();
            dio.Pin["KillBird"].Get();
            //dio.Pin["NonExistant"].Set(); //exception
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

Пины здесь представляют собой серию линий ввода-вывода в цифровом блоке ввода-вывода, которые могут быть высокими (1) или низкими (0).

Я хотел бы использовать динамический для вызова следующим образом:

        dio.Pins.KillBird.Get();

Мой класс устройств ввода-вывода выглядит следующим образом, и, как вы заметите, я немного продвинулся в том, как реализовать динамический интерфейс, за исключением использования ключевого слова dynamic.

class IODevice
{
    public IODevice()
    {
        pin = new PinCollection();
        pin.Add(new Pin("IsBirdInCageSensor", 0));
        pin.Add(new Pin("KillBird", 1));
    }

    private PinCollection pin;
    public PinCollection Pin { get { return pin; } }

    public dynamic Pins { get; private set; }
}

Второй вопрос: каковы недостатки использования такой конструкции? (кроме отсутствия строгой проверки типов - чего у меня нет в любом случае)

1 Ответ

2 голосов
/ 14 марта 2010

Если вы хотите продолжить использовать существующий тип PinCollection, тогда PinCollection должна реализовать IDynamicMetaObjectProvider . Тогда Pins возвращает тот же PinCollection, что и Pin, но, поскольку он был напечатан как динамический, допускается синтаксис obj.Pins.KillBird (а ваша реализация GetMetaObject преобразует это в доступ к словарям в PinCollection).

Если вы можете изменить свою реализацию, вы можете вместо этого использовать класс ExpandoObject :

private ExpandoObject _pins;
public dynamic Pins { get { return _pins; } }

ExpandoObject - это словарь, в котором уже есть метаобъект, который преобразует динамические обращения к свойствам в доступы к словарям. Обратите внимание, что в этом случае вам придется избавиться от строго типизированного PinCollection или придумать способ синхронизации двух: вы не хотите, чтобы в этих двух местах хранились разные данные контактов.

...