Как реализовать саминициализирующий сеттер в c # - PullRequest
0 голосов
/ 21 февраля 2019

Я хочу использовать информацию, скрывающуюся с установленным аксессором свойства.Поэтому я хочу активировать установленный аксессор, не добавляя в него никакого значения.В set acessor происходит инициализация значения, например:

    /// <summary>
    ///     load short ref controls
    /// </summary>
    /// <param name="reset">(re)set cached list</param>
    public List<ShortRef_Control> ShortRefControls
    {
        // (re)set cached list
        set
        {
            tableDictionary["refcontrols"] = 
              (from src in dataContext.ShortRef_Controls select src).ToList();
        }

        // return cached list
        get
        {
            return tableDictionary.Get<List<ShortRef_Control>>("refcontrols");
        }
    }

Вопрос : Почему я хочу это сделать? Ответ : Две причины: 1. Я также хочу сбросить это, я использую кэшированный список таблицы со строками из базы данных.Когда эта таблица обновляется, я хочу обновить кэшированный список.Я не хочу использовать трудно читаемые сеттеры для этого и поэтому хочу скрыть инициализацию сеттера. 2. Я использую имена клавиш, тогда возможны ошибки при наборе, держать эти имена вместе - отличное решение. Что работает? Возможно, не очень удачное решение: ShortRefControls = null

В языке C # чего-то не хватает? Или я (не) использую свойства таким образом.ShortRefControls = null работает, но если другой коллега поддерживает этот код, у него может сложиться впечатление, что для значения ShortRefControls установлено значение null.

Лучшее решение, которое я могу придумать, - не использовать свойства для этого иИспользуйте отдельную функцию GetShortRefControls () и SetShortRefControls ().

ОБНОВЛЕНИЕ : Я (ах ... мой коллега ;-) придумал это:

    /// <summary>
    ///     load short ref controls
    /// </summary>
    private void SetShortRefControls() => ShortRefControls = (from src in dataContext.ShortRef_Controls select src).ToList();

Эта частная функция используется в качестве установочного значения.В некотором смысле это ведет себя как псевдоним или обертка для сеттера. Что с этим не так? Это дополнительная функция, которая на самом деле не нужна.

C # версия x? Странно думать, что ShortRefControls =< инициализируется с помощьюнет значения, это способ справиться с этим в будущей версии C #.Символы = <</strong> могут отличаться от любых символов, что означает самостоятельную инициализацию.Чтобы позволить установщику вести себя так, как следует установщику, = говорит, что ShortRefControls должен получить значение, <</strong> говорит, что оно будет инициализировано само по себе и не будет передано как значение.

ОБНОВЛЕНИЕ 2 : После долгих раздумий я придумал следующее:

/// <summary>
///     load short ref controls
/// </summary>
/// <param name="set">(re)set content cached list</param>
public List<ShortRef_Control> ShortRefControlList(bool set = false)
{
    // set or reset cache
    if (set)
      tableDictionary["refcontrols"] = 
        (from src in dataContext.ShortRef_Controls select src).ToList();

    // always return content of cache
    return tableDictionary.Get<List<ShortRef_Control>>("refcontrols");
}

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

То, что я пробовал и не работало: ShortRefControls = SelfInitialising.Это может быть хорошим решением.SelfInitialising - это переменная с нулевым значением.Это проясняет, какой будет смысл.Проблема в том, что у меня есть не только ShortRefControls в tableDictionary, но и намного больше данных с разными типами, так что это не поможет.

Что мне действительно нужно: самоинициализирующийся установщик

Так есть ли лучшая альтернатива для решения этой проблемы или хороший совет для команды Visual Studio по расширению языка?

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

Вы можете инициализировать кеш в конструкторе и не использовать установщик.Затем на основе ваших предопределенных условий (ShouldReload) получатель может перезагрузить кеш.Вы можете сделать метод Reload частным / публичным в зависимости от того, хотите ли вы дать пользователям этого класса возможность перезагружать кеш явно.

0 голосов
/ 19 марта 2019

Как насчет расширения решения ozanmut и использования индексатора для указания имен таблиц?

Это сохранит чистую схему Озанмута, а также поможет решить ваши проблемы с обработкой нескольких таблиц:


    public class Tables
    {
        private readonly IDictionary<string, List<ShortRef_Control>> tableDictionary = new Dictionary<string, List<ShortRef_Control>>();

        public List<ShortRef_Control> this[string tableName]
        {
            get
            {
                if (ShouldReload(tableName))
                    Reload(tableName);

                return tableDictionary[tableName];
            }
        }

        public void Reload()
        {
            foreach (var tableName in tableDictionary.Keys)
                Reload(tableName);
        }

        private void Reload(string tableName)
        {
            // implement table-specific loading logic here:
            switch (tableName)
            {
                case "refcontrols":
                {
                    tableDictionary[tableName] = (from src in dataContext.ShortRef_Controls select src).ToList();
                    break;
                }
                default:
                {
                    throw new NotSupportedException($"invalid table name: {tableName}");
                }
            }

            // note: in the real world I wouldn't use a switch statement to implement the logic, but this is just to 
            // illustrate the general concept
        }

        private bool ShouldReload(string tableName)
        {
            return tableDictionary[tableName] == null || !tableDictionary[tableName].Any();
        }
    }


    public class TestClass
    {
        private readonly Tables tables = new Tables();

        public TestClass()
        {
            tables.Reload();
        }

        // this indexer will allow you to access your various tables from outside this class by specifying the table name
        public List<ShortRef_Control> this[string name]
        {
            get { return tables[name]; }
        }

        // if you need your table names hard-coded, you can create separate properties for each one:
        public List<ShortRef_Control> RefControlsTable { get { return this["refcontrols"]; }}

        // here's a few examples of how the tables would be accessed or used

        public void UseTableRefControl()
        {
            UseTableRefControl(DoSomethingWithRecord);
        }

        public void UseTableRefControl(Action<ShortRef_Control> action)
        {
            TakeActionOnTable("refcontrols", DoSomethingWithRecord);
        }

        public void TakeActionOnTable(string tableName, Action<ShortRef_Control> action)
        {
            foreach (var row in tables[tableName])
                action(row);
        }

        private static void DoSomethingWithRecord(ShortRef_Control row)
        {
            // do something with the row here
        }
    }
0 голосов
/ 28 февраля 2019

Вы правы в том, что язык не поддерживает синтаксис для инициализации сеттера.

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

На мой взгляд, ShortRefControls должно быть свойством только для чтения:

public List<ShortRef_Control> ShortRefControls
{
    // return cached list
    get
    {
        return tableDictionary.Get<List<ShortRef_Control>>("refcontrols");
    }
}

Примечание: вы можете сократить эток следующему:

public List<ShortRef_Control> ShortRefControls =>
    tableDictionary.Get<List<ShortRef_Control>>("refcontrols");

Далее, чтобы обновить кэш для tableDictionary.Этого не следует делать в установщике свойств: аргумент value не используется, поэтому он не устанавливает свойство, он делает что-то еще.Вызывающие абоненты будут сбиты с толку, потому что этот код не делает то, что, как кажется, делает:

someObject.ShortRefControls = null;

null игнорируется, но ShortRefControls устанавливается на какое-то другое значение ,Это удивило бы большинство разработчиков, глядя на код.

Метод SetShortRefControls делает то, что вам нужно для обновления словарной статьи.Важный вопрос - , когда , который должен быть вызван.Из фрагментов кода трудно сказать, но есть некоторые возможности:

  1. Как часть средства доступа get для ShortRefControls.Это гарантировало бы, что словарь всегда актуален.Но это фактически делает ненужным хранение кэшированного значения.
  2. В ответ на какой-то другой метод (или методы), который делает недействительным кэш.Я не могу сказать, что это было бы из предоставленного фрагмента.
  3. Через некоторое время.Опять же, без большего контекста, я не могу сказать, какой период времени будет правильным.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...