Обработка пользовательских исключений с классом свойств в C# - PullRequest
1 голос
/ 10 июля 2020

Я знаю, что это уже заданный вопрос. Мне нужно разработать определяемую пользователем обработку исключений вместе с классом свойств, но я не получаю только что добавленное свойство (свойства DSMException.cs) Исключения. Я прошел через эти два решения -

Пользовательское исключение со свойствами

Каков правильный способ сделать пользовательский. NET Исключение сериализуемым?

У меня есть класс Property -DSMException, который содержит три свойства Type, Message, InnerExceptionMessage, которые необходимо передать.

DSMException.cs

 public class DSMException
    {
        public string Type { get; set; }
        public string Message { get; set; }
        public string InnerExceptionMessage { get; set; }
    }

Дан соответствующий настраиваемый класс исключения.

FatalException.cs

 public class FatalException :Exception
    {
        DSMException exception = new DSMException();
        public FatalException():base()
        {

        }

        public FatalException(string? Message): base(Message)
        {
            exception.Type = "FATAL";
            exception.Message = "MESSAGE:" + Message;
        }

        public FatalException(string? Message,Exception ex) : base(Message,ex)
        {
            exception.Type = "FATAL";
            exception.Message = "MESSAGE: " + ex.Message;
            exception.InnerExceptionMessage = "MORE DET: " + ex.ToInnerMostException().Message;
        }
    }

Я выбрасываю исключения, подобные приведенному ниже коду Channel. cs

 public override void Run(ServiceSettings settings, DataSource dataSource, string path)
 {
 try
{
  var channel = entities.Channels
         .Where(c => c.Name == parameters.Channel)
         .FirstOrDefault();
    if (channel != null)
      {
        // ANY LOGIC
      }
   else
    {
      throw new FatalException("Invalid Channel Name !!!");
    }
}
 catch (FatalException ex)// for channel is null
 {
     throw ex;
 }
catch (Exception ex)
 {
    throw ex;
 }
}

Ошибка возникает здесь при перехвате исключений-FatalExceptions

FolderInvocation.cs (Ошибка)

 private void DoFolderInvocation(DataSource dataSource, Plugin plugin)
{
  // Do type invocation
try
 {
 result = helper.Invoke(importableFile.Path);// This invokes the Run method, I skipped those codes

 if (result == null)
     logger.WriteError($"{dataSource.Key}: Unknown error while processing file '{importableFile.Path}'.");
else if (result.Success == false)
      logger.WriteError($"{dataSource.Key}: Error while processing file '{importableFile.Path}'. 
      {result.Message}");
 else
     logger.WriteDebug($"{dataSource.Key}: File '{importableFile.Path}' was processed successfully. 
     {result.Message}");
 }
 catch (FatalException exFatal)// **Problem Arises here-> need to get Ex.Type in the FatalException**
 {
   logger.WriteError($"{dataSource.Key}: An error occurred while processing data source: 
   {exFatal.Message}");
    throw exFatal;
 }
 catch (Exception ex)
{
 logger.WriteError($"{dataSource.Key}: Invocation error while processing file '{importableFile.Path}'. 
 {ex.Message}");
}
}

Что мне не хватает, так как этот минимальный воспроизводимый код верен, но мне нужно получить Ex.Type в FatalException. Пожалуйста, посоветуйте мне.

1 Ответ

1 голос
/ 10 июля 2020

Если я вас правильно понял, вам просто нужно переслать поля как publi c properties:

public class FatalException: Exception
{
    private readonly DSMException _exception = new DSMException();

    /* ... snip ... */

    public string MyType => _exception.Type;
    public string MyMessage => _exception.Message;
    public string MyInnerExceptionMessage => _exception.InnerExceptionMessage;
}

Однако, похоже, это немного нарушает цель класса DSMException. Вы могли бы сделать DSMException свойством publi c, но я настоятельно рекомендую заранее сделать его неизменяемым.

Я, очевидно, не знаю предполагаемого назначения DSMException, однако, поскольку все значения в любом случае собираются в конструкторах, вы также можете напрямую присвоить publi c свойства:

public FatalException(string? Message): base(Message)
{
    Type = "FATAL";
    Message = "MESSAGE:" + Message;
}

public string MyType { get ; }
public string MyMessage { get ; }
public string MyInnerExceptionMessage { get ; }

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

public sealed class DSMException
{
    public DSMException(string type, string message, string innerMessage)
    {
        Type = type;
        Message = message;
        InnerExceptionMessage = innerMessage;
    }

    public string Type { get; }
    public string Message { get; }
    public string InnerExceptionMessage { get; }
}

... а затем просто сделать его свойством publi c:

public class FatalException: Exception
{
    /* ... snip ... */

    public DSMException DSM => _exception;
}

Похоже, что вам все равно придется дублировать большую часть кода конструктора в FatalException, ErrorException, WarningException et c.

Также обратите внимание, что пока ваши пользовательские исключения только летают в том же AppDomain, все нормально; в тот момент, когда они могут пересекать границы домена (например, по проводам), DSMException должен быть сериализуемым, а также должны быть реализованы методы сериализации ваших пользовательских исключений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...