Назначить Generic Exception <TException> сообщение

1

Поскольку я делаю много аргументов нулевой проверки, я хотел немного упростить ее. Я создал следующий метод:

public static void ThrowExceptionIf<TException>(bool condition, string message = null, params KeyValuePair<string, string>[] data) where TException : Exception, new()
{
    if (condition)
    {
        return;
    }

    var exception = new TException();
    data.AsParallel().ForAll(d => exception.Data.Add(d.Key, d.Value));

    throw exception;
}

Используется как:

public ValidatableBase(IUser user, IEventAggregator eventService)
    : this()
{
    ExceptionFactory
        .ThrowExceptionIf<ArgumentNullException>(user == null || eventService == null);
    this.user = user;
    this.EventService = eventService;
}

Однако проблема заключается в том, что я не могу назначить сообщение для исключения. Свойство Message является readonly, а generic не видит, что принудительный тип принимает параметры.

Я видел, что некоторые экземпляры экземпляра CustomException и передают сообщение через свой конструктор и назначают InnerException как заданное исключение (в данном случае TException), но я хотел спросить, есть ли какие-либо альтернативы перед тем, как идти по этому маршруту. Обертывание всех исключений, сбрасываемых фабрикой в обычном исключении, похоже на плохой дизайн.

редактировать

Заключительная фабрика использует комбинацию всех ответов и отлично работает.

public static void ThrowExceptionIf<TException>(bool condition, string message = null, IUser user = null, params KeyValuePair<string, string>[] data) where TException : Exception, new()
{
    ThrowExceptionIf<TException>(
        condition,
        () => (TException) Activator.CreateInstance(typeof (TException), message), 
        user, 
        data);
}

public static void ThrowExceptionIf<TException>(Func<bool> predicate, string message = null, IUser user = null, params KeyValuePair<string, string>[] data) where TException : Exception, new()
{
    ThrowExceptionIf<TException>(predicate(), message, user, data);
}

public static void ThrowExceptionIf<TException>(bool condition, Func<TException> exception, IUser user = null, params KeyValuePair<string, string>[] data) where TException : Exception, new()
{
    if (condition)
    {
        return;
    }

    TException exceptionToThrow = exception();
    AddExceptionData(exceptionToThrow, user, data);

    throw exceptionToThrow;
}

public static void AddExceptionData(Exception exception, IUser user = null, params KeyValuePair<string, string>[] data)
{
    foreach (var exceptionData in data)
    {
        exception.Data.Add(exceptionData.Key, exceptionData.Value);
    }

    if (user != null)
    {
        exception.Data.Add("User", user.RacfId);
    }
}

Теперь я могу использовать метод ThrowExceptionIf следующими способами

ThrowExceptionIf<ArgumentNullException>(
    user == null,
    "Users can not be null.");

ThrowExceptionIf<ArgumentNullException>(
    user == null,
    () => new ArgumentNullException("user", "Users can not be null"));

ThrowExceptionIf<ArgumentException>(
    () => user.FirstName.Equals(user.LastName),
    "last name must not equal the first name");

Спасибо за помощь!

  • 1
    Вы используете один и тот же объект исключения одновременно. Это неверно. Если бы это было допустимо, накладные расходы на выполнение этого затенили бы небольшую стоимость вставки в словарь.
  • 0
    Спасибо что подметил это
Теги:
generics
exception
factory-pattern

2 ответа

3
Лучший ответ

Вы также можете передать метод лямбда создания, а не сообщение, методу метания:

public static void ThrowExceptionIf<TException>(bool condition, Func<TException> init, params KeyValuePair<string, string>[] data) where TException : Exception
{
    if (condition)
    {
        return;
    }

    var exception = init();
    data.AsParallel().ForAll(d => exception.Data.Add(d.Key, d.Value));

    throw exception;
}

Затем вызовите ThrowExceptionIf(true,()=>new ArgumentNullException("foo")); ,

  • 0
    Спасибо, мне нравится, как это работает. Это дает мне большую гибкость.
2

Ты мог:

throw (TException)Activator.CreateInstance(typeof(TException), message, inner);
  • 0
    Мне это очень нравится, но я теряю способность предоставлять пользовательские данные
  • 0
    Разве вы не можете просто: TException myex = (TException)Activator.CreateInstanc...; myex.Data.Add(..); throw myex;
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню