Класс результата для передачи между слоями проекта

Постановка задачи

Я видел нечто подобное с Ремора Результаты, но не могу использовать из-за лицензии. Моя цель — создать экземпляр FooBarResult либо из результата, либо из ошибки, а затем передать его другому компоненту. В другом компоненте проверяется на IsSuccesful и в зависимости от этого выполняется либо BadRequest(FooBarResult.ErrorMsg), либо Ok(FooBarResult.Payload) (просто для примера).

Я слышал о монаде Либо, но не могу в ней разобраться. Вместо этого я попытался сделать это простым способом с классом FooBarResult. Однако на самом деле это небезопасно, так как я все еще могу использовать объект неправильным образом.

public class FooBarResult
{
    public bool IsSuccessful { get; set; }
    public string? Payload { get; set; }
    public string? ErrorMsg { get; set; }

    public FooBarResult(string error)
    {
        IsSuccessful = false;
        ErrorMsg = error;
    }
    
    public FooBarResult(string payload) // that won't work
    {
        IsSuccessful = true;
        Payload = payload;
    }
}

Вопрос

Как можно создать результирующий класс, содержащий полезную нагрузку и сообщение об ошибке, в зависимости от успеха операции, генерирующей результат? Может ли полезная нагрузка быть даже общим объектом T и ошибкой?

У вас есть особые цели для установки нить как обнуляемого? Строка является ссылочным типом и всегда допускает значение NULL.

RelativeLayouter 17.05.2022 14:59

Может быть, добавить статические методы Factory: FromResult(string) и FromError(string)? И поскольку вы уже рассматривали возможность использования третьих лиц: возможно, проверьте Ардалис/Результат.

Fildor 17.05.2022 15:01

Как насчет public FooBarResult(string stringValue, bool isError = false)?

Mathias R. Jessen 17.05.2022 15:01
«Может ли полезная нагрузка быть даже общим T-объектом, а также ошибкой?» — Конечно. Но для Error это не имеет особого смысла. В любом случае, что делает хорошее представление Error: описательный текст, может быть, код и, может быть, вызывающее исключение, верно?
Fildor 17.05.2022 15:06

@RelativeLayouter - начиная с C# 8, вы можете настроить компилятор так, чтобы ссылочные типы НЕ допускали значение NULL по умолчанию, чтобы вам не приходилось везде проверять нулевые значения.

scottdavidwalker 17.05.2022 15:09

Если вы не в курсе, эта библиотека только что изменилась (2 дня назад) с AGPL на LGPL. Я не знаю, имеет ли это значение для того, можете ли вы использовать его или нет.

DiplomacyNotWar 17.05.2022 15:10

@Fildor Статические фабричные методы - фантастическая идея, но я все еще могу использовать ее «неправильно». IsSuccessful может быть «ложным», но я все равно могу попытаться получить доступ к полезной нагрузке, которая может быть нулевой.

jkbx 17.05.2022 15:18

@jkbx Я не думаю, что вы можете на 100% избежать этого, если хотите / должны представлять как ошибку, так и успех в одной абстракции. Вы, мог, конечно, реализуете геттеры, чтобы генерировать какое-то исключение, если используется «неправильно», поэтому вы «быстро терпите неудачу», если в коде есть ошибка использования.

Fildor 17.05.2022 15:21
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
8
33
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для части «избегайте неправильного использования» вы мог делаете что-то вроде этого (лично я бы этого не сделал, но эй...)

public class FooBarResult
{
     public bool IsSuccessful {get; set;}

     // just doing one to demonstrate
     private string _payload;
     public string Payload
     {
         // InvalidOperationException is the ...
         // "The exception that is thrown when a method call is invalid 
         //  for the object's current state."
         get { 
               if(IsSuccessful) return _payload; 
               throw new InvalidOperationException(); 
             }
         set { _payload = value; }
     }
}

См. https://dotnetfiddle.net/fqpSQS

Для справки:

Инвалидоператионексцептион

Разум : Это может привести к проблемам, как только вы попытаетесь сериализовать/десериализовать.

Это подходит для меня. Сериализация/десериализация результата не сработает, вы это имеете в виду?

jkbx 17.05.2022 15:58

Из коробки не получится, да. Сериализатор может попытаться прочитать все свойства, конечно, не зная о семантических связях между ними («X действителен, только если Y истинен...»).

Fildor 17.05.2022 16:01

Другие вопросы по теме