Поскольку я делаю много аргументов нулевой проверки, я хотел немного упростить ее. Я создал следующий метод:
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");
Спасибо за помощь!
Вы также можете передать метод лямбда создания, а не сообщение, методу метания:
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"));
,
Ты мог:
throw (TException)Activator.CreateInstance(typeof(TException), message, inner);
TException myex = (TException)Activator.CreateInstanc...; myex.Data.Add(..); throw myex;