将泛型类型的实例作为参数传递给泛型类的动态实例

时间:2012-02-14 15:56:16

标签: c# generics dynamic exception-handling

我正在尝试构建一个实际类型为ExceptionLogCondition的动态类型列表,它是一个定义需要解除的异常类型的类,以及特定异常类型的可选条件谓词。 / p>

问题在于将异常传递给IsConditionValid(T e)方法。我总是得到这个例外:

  

最佳重载方法匹配   'MvcApplication.ErrorLogCondition.IsConditionValid(Exceptions.AjaxOnlyViolationException)'   有一些无效的论点

堆栈跟踪:

  

在CallSite.Target(Closure,CallSite,Object,Exception)中   System.Dynamic.UpdateDelegates.UpdateAndExecute2 [T0,T1,TRET](调用点   site,T0 arg0,T1 arg1)at   CONCENTRA.MOS.MvcApplication.ErrorLog_Filtering(对象发送者,   ExceptionFilterEventArgs e)在C:_teamprojects \ Main \ Source \ Global.asax.cs中:行   213在Elmah.ErrorLogModule.OnFiltering(ExceptionFilterEventArgs   Args)at Elmah.ErrorLogModule.LogException(Exception e,HttpContext   上下文)在Elmah.ErrorLogModule.OnError(Object sender,EventArgs   args)at System.EventHandler.Invoke(Object sender,EventArgs e)
  在System.Web.HttpApplication.RaiseOnError()

以下是代码:

public class MvcApplication : System.Web.HttpApplication
{
    protected void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e)
    {
        var exceptionsToDismiss = new List<dynamic>() {
            new ErrorLogCondition<Exceptions.AjaxOnlyViolationException>(),
            new ErrorLogCondition<WebsiteException>(c => c.LogError == true)
        };

        foreach (var exd in exceptionsToDismiss)
        {
            if(((Type)exd.ExceptionType).Equals(e.Exception.GetBaseException().GetType()) &&
                exd.IsConditionValid(e.Exception.GetBaseException()))
                // The second condition fails even though the type is correct (see first if condition).
                e.Dismiss();
        }
    }
}

public class ErrorLogCondition<T> where T : Exception, new() { 
    public Type ExceptionType {get;set;}
    public Predicate<T> ExceptionTypeCondition { get; set; }

    public ErrorLogCondition() {
        ExceptionType = typeof(T);
    }

    public ErrorLogCondition(Predicate<T> c)
    {
        ExceptionType = typeof(T);
        ExceptionTypeCondition = c;
    }

    public bool IsConditionValid(T e)
    { 
        return ExceptionTypeCondition == null || ExceptionTypeCondition.Invoke(e);
    }
}

我的直觉是说我可能会有点过头了。所以我愿意接受其他建议。不过我还想知道为什么这不起作用。

3 个答案:

答案 0 :(得分:3)

GetBaseException()会返回Exception,而不是IsConditionValid可以接受的内容。你有这个代码的道德等价物:

Exception baseExp = e.Exception.GetBaseException() //which is a AjaxOnlyViolation
IsConditionValid( baseExp);

//where isconditionvalid is:
bool IsConditionValid(AjaxOnlyViolation e) { }

运行时的实例在运行时是一个AjaxOnlyViolation并不重要 - 编译器不知道这一点。重要的是声明它可能是任何异常,并且没有从ExceptionAjaxOnlyViolation的隐式强制转换。因此,错误。

你需要告诉编译器;您可以更改IsConditionValid以接受异常,然后将其转换为该方法内的T,或者在调用方法之前将其强制转换。

答案 1 :(得分:1)

从提供的代码中扣除 e.Exception.GetBaseException()返回不能转换为AjaxOnlyViolationException类型的类型的实例。

答案 2 :(得分:1)

由于GetBaseException()返回类型为Exception,因此无法找到方法public bool IsConditionValid(Exception e)。您应该在签名中提供Exception类型的方法。

尽管如此,这可能不是解决性能问题的更好方法(参见MSDN关于动态)。

但你可以使用一个List<Predicate<Exception>>来做同样的工作,同时减少所需的代码行,恕我直言。