Как переключать состояние в методе C# .NET

118
11 октября 2019, 15:00

Реализую простой фасад для сокрытия более низкоуровневых решений. Есть модель данных:

public class OutControl
{
    //---------Первая группа---------//
    public const byte Call = 0x00;
    public const byte Nop = 0x01;
    public const byte Alarm = 0x02;
    public const byte Warning = 0x03;
    public const byte Nol = 0x04;
    public const byte Action = 0x05;
    public const byte Pull = 0x06;
    //---------Вторая группа---------//
    public const byte Push = 0x00;
    public const byte Buzzer = 0x01;
    public const byte Temp = 0x02;
    public const byte Ring = 0x03;
    public const byte SwitchOff = 0x04;
    public const byte SwitchOn = 0x05;
    public const byte Reverse = 0x06;
    public const byte Reserve = 0x07;
    //-------Опкоды для записи в определенный блок------//
    public const byte FirstBlock = 0x06; 
    public const byte SecondBlock = 0x07;
}

Загвоздка в том, что каждая переменная относиться к определенному блоку. Первая группа (7 переменных) к FirstBlock, вторая к SecondBlock, опкоды идентичны. Не могу понять, как можно автоматически переключать между блоками, что бы в дальнейшем в main просто вызвать метод:

static void Main(string[] args)
{
    Facade facade = new Facade();
    facade.SetData(Model.OutControl.Buzzer, true);
}

Минуя установку блока. В метод передать только константу с опкодом, и булеву переменую для взвода флага:

public class Facade
{
    private Model.OutControl _outs;
    public Facade()
    {
        _outs = new Model.OutControl();
    }
    public void SetData(byte outs, bool action)
    {
        switch (как можно переключать?)
        {
            case ?:
                _outs.Set(Model.OutControl.FirstBlock, outs, action);
                break;
            case ?:
               _outs.Set(Model.OutControl.SecondBlock, outs, action);
                break;
        }
    }
}

Как решение в лоб, перебрать каждый блок в if(), но сдается мне, что можно более элегантнее сделать. Например, заменить полиморфизмом?

Answer 1
interface IOperation
{
    byte OpCode { get; }
    byte BlockCode { get; }
}
class Operations
{
    const byte FirstBlock = 0x06; 
    const byte SecondBlock = 0x07;
    public readonly IOperation Call = new OperationImpl(0x00, FirstBlock);
    public readonly IOperation Nop = new OperationImpl(0x01, FirstBlock);
    ...
    public readonly IOperation Push = new OperationImpl(0x00, SecondBlock);
    public readonly IOperation Buzzer = new OperationImpl(0x01, SecondBlock);
    ...
    class OperationImpl : IOperation
    {
        public byte OpCode { get; }
        public byte BlockCode { get; }
        public OperationImpl(byte opCode, byte blockCode)
            => (OpCode, BlockCode) = (opCode, blockCode);
    }
}
class Facade
{
    ...
    public void SetData(IOperation operation, bool action)
        => _outs.Set(operation.OpCode, operation.BlockCode, action);
}

У нас же ООП, ну чего вы в самом деле? :)

Answer 2

Очевидно, что тебе необходимо какое-то разделение. И самым правильным способом здесь будет замена констант на Enum'ы.

    //---------Первая группа---------//
enum First : byte
{
    Call = 0x00,
    Nop = 0x01,
    Alarm = 0x02,
    Warning = 0x03,
    Nol = 0x04,
    Action = 0x05,
    Pull = 0x06,
}
    //---------Вторая группа---------//
enum Second : byte
{
    Push = 0x00,
    Buzzer = 0x01,
    Temp = 0x02,
    Ring = 0x03,
    SwitchOff = 0x04,
    SwitchOn = 0x05,
    Reverse = 0x06,
    Reserve = 0x07
}
public void SetData(First outs, bool action)
{
    _outs.Set(Model.OutControl.FirstBlock, (byte)outs, action);
}
public void SetData(Second outs, bool action)
{
    _outs.Set(Model.OutControl.SecondBlock, (byte)outs, action);
}

Но пока непонятно - как этот инструмент используется. И если опкоды просто читаются из файла и нужно определить - к какой категории они онтосятся, а опкоды одинаковы... Ну, извините - недостаточно информации для распределения. Но ведь интерпретатор как-то их разделяет. Используй тот же признак.

Answer 3

Если хочется сделать этот выбор скрыто для пользователя, то можно сделать опкоды в разных диапазонах или в разной разрядной сетке.

Например, секция один имеет опкоды в диапазоне 1-10, а вторая в 20-30.

Внутри своего метода, видишь, что опкод был передан в диапазоне 20-30 и понимаешь, что речь идет о второй секции.

Правда, в коде- это будет смотреться не интуитивно понятно...

И еще в голову пришел 1 вариант, менее "дикий":

Можно заменить числовые константы на строки, а внутри класса хранить словарик Dictionary<string,Typle<byte,byte>- где первый элемент кортежа- это опкод, а второй секция.

Твой метод будет принимать строку, а уже внутри ты через словарь можешь получить опкод.

READ ALSO
Не работает асинхронный вызов метода C#

Не работает асинхронный вызов метода C#

Имеется метод, который внутри себя запускает дважды другой метод, но второй раз асинхронноИ вот внутри Task не срабатывает SaveToDB()

141
накопление вызовов корутин

накопление вызовов корутин

Есть такая реализация: переходы три перехода между играми, когда мы перешли, срабатывает некий метод с корутиной в 3 секунды, но если очень...

118
Реализовать страницы в winforms

Реализовать страницы в winforms

В окно из бд загружаются данныеНо нужно сделать чтобы загрузилось не все сразу

117
Получение списка кошельков Bitcoin

Получение списка кошельков Bitcoin

Пишу аналог сайта Mnemonic Code Converter на C# Дошел до получения BIP32 Extended Private Key и BIP32 Extended Public KeyИспользую библиотеку NBitcoin

142