C# 将泛型类型的实例作为泛型类的动态实例上的参数传递

C# 将泛型类型的实例作为泛型类的动态实例上的参数传递,c#,generics,dynamic,exception-handling,C#,Generics,Dynamic,Exception Handling,我试图构建一个动态类型列表,它实际上是ExceptionLogCondition类型,它是一个定义需要排除的异常类型和特定异常类型的可选条件谓词的类 问题在于将异常传递给IsConditionValid(te)方法。我总是遇到这样的例外: 匹配的最佳重载方法 'MVCAPApplication.ErrorLogCondition.IsConditionValid(Exceptions.AjaxOnlyViolationException)' 有一些无效的参数 堆栈跟踪: 目标(闭包、调用站点、对

我试图构建一个动态类型列表,它实际上是
ExceptionLogCondition
类型,它是一个定义需要排除的异常类型和特定异常类型的可选条件谓词的类

问题在于将异常传递给
IsConditionValid(te)
方法。我总是遇到这样的例外:

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

堆栈跟踪:

目标(闭包、调用站点、对象、异常)位于 System.Dynamic.UpdateLegates.UpdateAndExecute2[T0,T1,TRet](调用站点 站点,T0 arg0,T1 arg1)位于 CONCENTRA.MOS.mvcapapplication.ErrorLog_筛选(对象发送方, C中的ExceptionFilterEventArgs(e):\u teamprojects\Main\Source\Global.asax.cs:line 213在Elmah.ErrorLogModule.OnFiltering(例外的FilterEventArgs args)位于Elmah.ErrorLogModule.LogException(异常e,HttpContext 上下文)位于Elmah.ErrorLogModule.OnError(对象发送方,EventArgs args)位于System.EventHandler.Invoke(对象发送方,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);
    }
}
公共类MVCAPApplication:System.Web.HttpApplication
{
受保护的无效错误日志\u筛选(对象发送方,ExceptionFilterEventArgs e)
{
var exceptionsToDismiss=新列表(){
新的ErrorLogCondition(),
新的ErrorLogCondition(c=>c.LogError==true)
};
foreach(异常ToDismiss中的var exd)
{
if(((Type)exd.ExceptionType).Equals(e.Exception.GetBaseException().GetType())&&
exd.IsConditionValid(e.Exception.GetBaseException())
//即使类型正确,第二个条件也会失败(请参阅第一个if条件)。
e、 解雇();
}
}
}
公共类ErrorLogCondition,其中T:Exception,new(){
公共类型异常类型{get;set;}
公共谓词ExceptionTypeCondition{get;set;}
公共ErrorLogCondition(){
例外类型=类型(T);
}
公共ErrorLogCondition(谓词c)
{
例外类型=类型(T);
ExceptionTypeCondition=c;
}
公共边界条件有效(T e)
{ 
返回ExceptionTypeCondition==null | | ExceptionTypeCondition.Invoke(e);
}
}
我的直觉告诉我可能做得有点过头了。因此,我愿意接受其他建议。尽管如此,我还是想知道为什么这不起作用。

从提供的代码中我扣除
e.Exception.GetBaseException()
返回一个类型的实例,该实例不可强制转换为
AjaxOnlyViolationException
类型。

从提供的代码中我扣除
e.Exception.GetBaseException())
返回类型的实例,该实例不可强制转换为
AjaxOnlyViolationException
类型。

GetBaseException()
返回一个
异常
,该异常不是
IsConditionValid
可以接受的。你在道德上等同于这一准则:

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

//where isconditionvalid is:
bool IsConditionValid(AjaxOnlyViolation e) { }
运行时的实例是否是运行时的AjaxOnlyViolation并不重要——编译器不知道这一点。重要的是,它被尽可能地声明为任何异常,并且没有从
exception
AjaxOnlyViolation
的隐式转换。因此,错误

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

GetBaseException()
返回一个
异常
,这不是
IsConditionValid
可以接受的。你在道德上等同于这一准则:

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

//where isconditionvalid is:
bool IsConditionValid(AjaxOnlyViolation e) { }
运行时的实例是否是运行时的AjaxOnlyViolation并不重要——编译器不知道这一点。重要的是,它被尽可能地声明为任何异常,并且没有从
exception
AjaxOnlyViolation
的隐式转换。因此,错误

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

因为
GetBaseException()
返回类型为
Exception
,无法找到任何方法
公共bool IsConditionValid(异常e)
。您应该在签名中提供一个带有
异常
类型的方法

然而,对于性能问题,这可能不是更好的方法(请参阅MSDN关于动力学)

但是您可以使用一个
列表
,它可以在减少所需代码行的同时完成相同的工作,IMHO。

因为
GetBaseException()
返回类型是
Exception
,找不到任何方法
公共bool IsConditionValid(Exception e)
。您应该在签名中提供一个带有
异常
类型的方法

然而,对于性能问题,这可能不是更好的方法(请参阅MSDN关于动力学)


但是你可以使用一个
列表
,它可以做同样的工作,同时减少所需的代码行,IMHO。

如果这是真的,第一个条件将失败,第二个条件将永远不会执行。@Peter:是的,但是你的methid需要AjaxOnlyViolationException,但是你向它传递一个基类型。您不能执行上转换。如果这是真的,第一个条件将失败,第二个条件将永远不会执行。@Peter:是的,但您的methid需要AjaxOnlyViolationException,但您向它传递了一个基类型。您不能执行上转换。您可能应该为
ErrorLogCondition
private:
public Type Exception的
ExceptionType
属性设置setter