Since I do a lot of argument null checking, I wanted to simplify it a little bit. I created the following method:
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;
}
Which is used like:
public ValidatableBase(IUser user, IEventAggregator eventService)
: this()
{
ExceptionFactory
.ThrowExceptionIf<ArgumentNullException>(user == null || eventService == null);
this.user = user;
this.EventService = eventService;
}
The problem however is that I can't assign a Message to the exception. The Message property is readonly and the generic doesn't see that the constrained Type accepts parameters.
I've seen some people instance a CustomException
and pass the message in through its constructor, and assign the InnerException
as a given exception (in this case TException
) but I wanted to ask if there was any alternatives before going that route. Wrapping all exceptions thrown by the factory in a custom exception seems like bad design.
The final factory uses a combination of everyones answers and works great.
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);
}
}
I can now use the ThrowExceptionIf
method in the following ways
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");
Thanks for the help!
You can also pass a creation lambda method, rather than a message, to the throwing method:
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;
}
Then call like ThrowExceptionIf(true, ()=>new ArgumentNullException("foo"));
.