public class ErrorCode
{
    public int HttpStatus { get; private set; }
    public string JsonErrorCode { get; private set; }
    public Type ExceptionT { get; private set; }

    public ErrorCode(string pJsonErrorCode, int pHttpStatus, Type pExceptionType)
    {
        this.HttpStatus = pHttpStatus;
        this.JsonErrorCode = pJsonErrorCode;
    }

    public void ThrowException(string pMsg)
    {
        throw Activator.CreateInstance(ExceptionT, pMsg);
    }
}

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

Protocol.ErrorCodes.Add
(
    ErrorCodeType.ElementClickIntercepted,
    new ErrorCode
    (
        "element click intercepted", 
        400, 
        typeof(ElementClickInterceptedException)
    )
);

Приведенный выше код не работает, поскольку создаваемый тип относится к типу object и не является производным от system.exception.

Приведенный выше код не будет работать с универсальными шаблонами, поскольку словарь должен понимать, что создается. Я не знаю, что здесь делать. в моем словаре около 50 разных исключений. Мысли?

0
Andrew Mills 9 Ноя 2019 в 00:19
Вы можете использовать интерфейс и использовать универсальные шаблоны в фактических реализациях интерфейса ... тогда ваш словарь может быть определен как Dictionary<ErrorCodeType, IErrorCode> (где IErrorCode - интерфейс)
 – 
user1538301
9 Ноя 2019 в 00:24

2 ответа

Вам необходимо преобразовать созданный экземпляр в Exception

public class ErrorCode
{
  public int HttpStatus { get; private set; }
  public string JsonErrorCode { get; private set; }
  public Type ExceptionT { get; private set; }

  public ErrorCode(string pJsonErrorCode, int pHttpStatus, Type pExceptionType)
  {
    this.HttpStatus = pHttpStatus;
    this.JsonErrorCode = pJsonErrorCode;
    this.ExceptionT = pExceptionType;
  }

  public void ThrowException(string pMsg)
  {
    throw (Exception)Activator.CreateInstance(ExceptionT, pMsg);
  }
}

Вы можете заменить Exception на ElementClickInterceptedException или что-нибудь еще.

Тест

var error = new ErrorCode("test", 1, typeof(ArgumentException));
try
{
  error.ThrowException("error");
}
catch ( Exception ex )
{
  Console.WriteLine(ex.Message);
}

Скрипка скрипки

Вывод

error
2
Olivier Rogier 9 Ноя 2019 в 21:44
Это не работает, потому что оно будет преобразовано как исключение, а не как ElementClickInterceptedException.
 – 
Andrew Mills
9 Ноя 2019 в 21:39
Таким образом, вы можете использовать ElementClickInterceptedException вместо этого, если оно наследуется от некоторого исключения.
 – 
Olivier Rogier
9 Ноя 2019 в 21:44
Да, но объект не знает об исключении ElementClickInterceptedException. Вопрос гласит, что у меня есть масса исключений, с которыми нужно иметь дело.
 – 
Andrew Mills
9 Ноя 2019 в 22:26
На первый взгляд, у этой проблемы нет решения, поскольку для ключевого слова throw требуется экземпляр типа исключения, и вы не можете динамически приводить результат CreateInstance, насколько я знаю, если вы не используете дженерики.
 – 
Olivier Rogier
9 Ноя 2019 в 22:34

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

Да, действительно можно, и это правильное решение. Вам просто нужно объявить базовый интерфейс для словаря поиска.

public interface IErrorCode
{
    int HttpStatus { get; }
    string JsonErrorCode { get; }
    void ThrowException(string pMsg);
}

public class ErrorCode<T> : IErrorCode where T : Exception
{
    public int HttpStatus { get; private set; }
    public string JsonErrorCode { get; private set; }

    public ErrorCode(string pJsonErrorCode, int pHttpStatus)
    {
        this.HttpStatus = pHttpStatus;
        this.JsonErrorCode = pJsonErrorCode;
    }

    public void ThrowException(string pMsg)
    {
        var exception = (T)Activator.CreateInstance
        (
            typeof(T), 
            new object[] { pMsg }
        );
        throw exception;
    }
}


//Declare the dictionary with the interface, not the concrete type
Protocol.ErrorCodes = new Dictionary<ErrorCodeType,IErrorCode>();

Protocol.ErrorCodes.Add
(
    ErrorCodeType.ElementClickIntercepted,
    new ErrorCode<ElementClickInterceptedException>
    (
        "element click intercepted", 
        400
    )
);

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

Чтобы получить статус HTTP:

var status = Protocol.ErrorCodes[key].HttpStatus;

Чтобы получить код ошибки Json:

var errorCode = Protocol.ErrorCodes[key].JsonErrorCode;

В общем, ваш код должен зависеть не от конкретных экземпляров, а от интерфейсов (согласно «D» в SOLID ).

1
John Wu 10 Ноя 2019 в 01:40
Это не работает для меня, так как у меня есть функции, возвращающие объекты кода ошибки, где я не знаю, какой интерфейс предоставить универсальному типу. Это также делает все как исключение. Поэтому при выдаче ошибок он просто генерирует исключения вместо ElementClickInterceptedExceptions.
 – 
Andrew Mills
9 Ноя 2019 в 21:44
Общедоступный статический ErrorCode GetErrorCode (ErrorCodeType pType) {Protocol.ErrorCodes.TryGetValue (pType, out ErrorCode errorCode); return errorCode; }
 – 
Andrew Mills
9 Ноя 2019 в 21:45
Обратите внимание, как эта функция возвращает код ошибки на основе ключа. Ну, я очень хорошо не могу вернуть значение, зная ключ и его исключение
 – 
Andrew Mills
9 Ноя 2019 в 21:46
Добавьте ErrorCode и все, что вам нужно, в общий интерфейс.
 – 
John Wu
9 Ноя 2019 в 23:42
1
Указание добавления в интерфейс таково, что вам не нужно выполнять приведение. Я отредактировал пример для иллюстрации.
 – 
John Wu
10 Ноя 2019 в 01:41