Добавление «свойства расширения» в классы в C#

Методы расширения позволяют добавлять новые методы к существующим классам, даже если у вас нет доступа к исходному коду классов. Например, пример Случайные двумерные массивы в примере C# показывает как добавить метод расширения к двумерным массивам, хранящим данные произвольного типа.

К сожалению, нет способа сделать свойства расширения, добавляющие свойство к существующему классу. Обычным решением, по крайней мере, для управления является сохранение дополнительных значений в свойстве Tag объекта. Это работает, но только для элементов управления и других классов, которые имеют свойство Tag. Он также упреждает свойство Tag для других целей и позволяет хранить только одно значение.

В этом примере добавляются методы расширения SetValue и GetValue в класс object, чтобы вы могли установить и получить любое количество новых свойств, значения для любого объекта.

В следующем коде показан класс ExtensionProperties, который добавляет новые методы расширения.

public static class ExtensionProperties
{
    // Хранение свойств.
    private static Dictionary>
        PropertyValues = new Dictionary<
            object, Dictionary>();

    // Установите значение свойства для элемента.
    public static void SetValue(this object item,
        string name, object value)
    {
        // Если у нас еще нет словаря для этого элемента,
        // сделай один.
        if (!PropertyValues.ContainsKey(item))
            PropertyValues[item] = new Dictionary();

        // Установите значение в словаре словаря.
        PropertyValues[item][name] = value;
    }

    // Возвращает значение свойства для элемента.
    public static object GetValue(this object item, string name,
        object default_value)
    {
        // Если у нас нет словаря для
        // этот элемент еще, верните значение по умолчанию.
        if (!PropertyValues.ContainsKey(item)) return default_value;

        // Если значение не находится в словаре,
        // возвращаем значение по умолчанию.
        if (!PropertyValues[item].ContainsKey(name))
            return default_value;

        // Возвращаем сохраненное значение.
        return PropertyValues[item][name];
    }

    // Удалить свойство.
    public static void RemoveValue(this object item, string name)
    {
        // Если у нас нет словаря для этого элемента, ничего не делайте.
        if (!PropertyValues.ContainsKey(item)) return;

        // Если значение не находится в словаре, ничего не делайте.
        if (!PropertyValues[item].ContainsKey(name)) return;

        // Удалить значение.
        PropertyValues[item].Remove(name);

        // Если словарь пуст, удалите его.
        if (PropertyValues[item].Count == 0)
            PropertyValues.Remove(PropertyValues[item]);
    }

    // Удалить словарь свойств объекта.
    public static void RemoveAllValues(this object item)
    {
        // Если у нас есть словарь для этого элемента, удалите его.
        if (PropertyValues.ContainsKey(item))
            PropertyValues.Remove(PropertyValues[item]);
    }
}

Класс начинается с объявления Dictionary с именем PropertyValues, который использует объекты для ключей и других объектов Dictionary для значений. Он будет искать объект в словаре верхнего уровня верхнего уровня, чтобы получить новое свойство Dictionary для этого объекта.

В «inner» Dictionary используются строки (имена «свойств расширения») для ключей и объектов для значений. Когда код находит «внутренний» словарь объекта, он использует его для поиска значений.

В «inner» Dictionary используются строки (имена «свойств расширения») для ключей и объектов для значений. Когда код находит «внутренний» словарь объекта, он использует его для поиска значений.

...

Метод GetValue также начинается с определения, содержит ли словарь PropertyValues Dictionary словарь для объекта. Если такой Dictionary не существует, метод возвращает значение по умолчанию, переданное в него как параметр.

Если существует «внутренний» Dictionary, метод определяет, содержит ли оно значение для требуемого «свойства расширения». Если такого значения нет, метод снова возвращает значение по умолчанию. Наконец, если «внутренний» Dictionary содержит значение для требуемого свойства расширения, метод возвращает его.

Метод RemoveValue удаляет значение из объектов Dictionary. Если в верхнем уровне PropertyValues Dictionary не содержится запись для объекта, метод ничего не делает. Наконец, если «внутренний» Dictionary содержит значение для свойства «extension», код удаляет его. Наконец, если «внутренний» Dictionary пуст, код удаляет его из словаря свойств PropertyValues верхнего уровня, поэтому он не становится загроможденным с помощью Dictionary объекты, которые больше не нужны.

Наконец, метод RemoveAllValues удаляет «внутренний» словарь объекта. Прежде чем уничтожить объект, которому вы присвоили «свойства расширения» с помощью этих методов расширения, вы должны удалить все его свойства. Если вы этого не сделаете, они продолжат занимать место в словарях. Хуже того, записи в объектах Dictionary будут содержать ссылки на сами объекты, так что они не могут быть легко утилизированы сборщиком мусора. Они будут исправлены в конце концов, но не так эффективно, как если бы вы удалили значения.

Следующий код показывает, как программа использует свойства расширения.

// Установите значение для текстового поля txtName.
private void btnSetValue_Click(object sender, EventArgs e)
{
    txtName.SetValue(txtName.Text, txtValue.Text);
    txtValue.Clear();
}

// Получаем значение из текстового поля txtName.
private void btnGetValue_Click(object sender, EventArgs e)
{
    txtValue.Text = txtName.GetValue(txtName.Text, "").ToString();
}

// Удалить значение из текстового поля txtName.
private void btnRemoveValue_Click(object sender, EventArgs e)
{
    txtName.RemoveValue(txtName.Text);
    txtValue.Clear();
}

Когда вы нажимаете кнопку «Установить значение», программа вызывает текстовое поле txtName в текстовом поле SetValue, передавая ему имя свойства и значение для его назначения.

Когда вы нажимаете кнопку «Получить значение», программа вызывает метод GetValue текстового поля, передавая ему имя свойства и значение по умолчанию, и отображает результат.

Когда вы нажимаете кнопку «Удалить значение», программа вызывает метод RemoveValue текстового поля, передавая ему имя свойства для удаления.

Источник: http://csharphelper.com/blog/2016/12/add-extension-properties-to-classes-in-c/

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Adblock
detector