【问题标题】:Pass an instance of a generic type as a parameter on a dynamic instance of a generic class将泛型类型的实例作为参数传递给泛型类的动态实例
【发布时间】:2012-02-14 15:56:15
【问题描述】:

我正在尝试构建一个动态类型列表,该列表实际上是 ExceptionLogCondition 类型,这是一个定义需要解除的异常类型和特定异常类型的可选条件谓词的类。

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

最好的重载方法匹配 'MvcApplication.ErrorLogCondition.IsConditionValid(Exceptions.AjaxOnlyViolationException)' 有一些无效的参数

堆栈跟踪:

在 CallSite.Target(Closure , CallSite , Object , Exception ) 在 System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,Tret](CallSite 站点,T0 arg0,T1 arg1) 在 CONCENTRA.MOS.MvcApplication.ErrorLog_Filtering(对象发送者, C:_teamprojects\Main\Source\Global.asax.cs:line 中的 ExceptionFilterEventArgs e) 213 在 Elmah.ErrorLogModule.OnFiltering(ExceptionFilterEventArgs args) 在 Elmah.ErrorLogModule.LogException(Exception e, HttpContext 上下文) 在 Elmah.ErrorLogModule.OnError(Object sender, EventArgs args) 在 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);
    }
}

我的直觉表明我可能做得有点过头了。所以我愿意接受其他建议。不过我也想知道为什么这不起作用。

【问题讨论】:

  • 您可能应该为ErrorLogConditionExceptionType 属性设置setter 私有:public Type ExceptionType { get; private set; }

标签: c# generics dynamic exception-handling


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 如果这是真的,第一个条件将失败,第二个条件将永远不会执行。
    • @Peter:是的,但是您的方法需要 AjaxOnlyViolationException,但是您将 BASE 类型传递给它。你不能做上投。
    【解决方案3】:

    由于GetBaseException()返回类型为Exception,所以找不到方法public bool IsConditionValid(Exception e)。您应该在签名中提供一个带有Exception 类型的方法。

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

    但是您可以使用 List&lt;Predicate&lt;Exception&gt;&gt; 来完成相同的工作,同时减少所需的代码行数,恕我直言。

    【讨论】:

    • 我会尝试使用List&lt;Predicate&lt;Exception&gt;&gt; 方法,听起来合乎逻辑。
    猜你喜欢
    • 2017-12-23
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多