分配Generic Exception <texception>消息</texception>

时间:2014-11-03 16:48:15

标签: c# exception generics factory-pattern

由于我做了很多参数null检查,我想稍微简化一下。我创建了以下方法:

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属性是只读的,并且泛型不会看到受约束的Type接受参数。

我见过一些人实例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");

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

您还可以将创建lambda方法而不是消息传递给throw方法:

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"));一样打电话。

答案 1 :(得分:2)

你可以:

throw (TException)Activator.CreateInstance(typeof(TException), message, inner);