【问题标题】:System.Reflection.TargetException: 'Non-static method requires a target.' only with VS 2017 not with VS 2013System.Reflection.TargetException:“非静态方法需要一个目标。”仅适用于 VS 2017 不适用于 VS 2013
【发布时间】:2018-02-15 23:52:25
【问题描述】:

我多年来一直在这个项目上使用KendoDynamicLinq 库,没有任何问题。我开始在同一个项目/代码上使用 VS 2017 社区版而不是 VS 2013,如果我使用 VS 2017 运行项目,我会收到以下异常: System.Reflection.TargetException: 'Non-static method requires a target.'

但如果我用 VS 2013 运行它,没问题,没有例外,一切正常。

我一直在为此绞尽脑汁,但似乎找不到答案。任何指向我的帮助或方向将不胜感激。

private static MethodInfo GetMethod(string methodName, MethodInfo methodTypes, int genericArgumentsCount)
        {
            var methods = from method in typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static)
                          let parameters = method.GetParameters()
                          let genericArguments = method.GetGenericArguments()
                          where method.Name == methodName &&
                            genericArguments.Length == genericArgumentsCount &&
                            parameters.Select(p => p.ParameterType).SequenceEqual((Type[])methodTypes.Invoke(null, genericArguments))
                          select method;
            return methods.FirstOrDefault();
        }

抛出的线是这样的:

parameters.Select(p => p.ParameterType).SequenceEqual((Type[])methodTypes.Invoke(null, genericArguments))

您是否在这里看到任何可以在 VS2013 中使用但在 VS 2017 中无法使用的东西。解决方案或目标框架没有变化。

【问题讨论】:

  • 问题其实出在传递methodTypes的GetMethod的调用者身上。他们应该选择静态方法并选择实例方法。就在我的脑海中,C# 编译器发生了变化,在那个时间范围内,将某些类型的 lambda 表达式从静态方法更改为单例闭包类的实例方法。
  • 谢谢,我会研究一下,很难说,这个库接收一个 IQuarable 集合并应用来自 UI Kendo 网格的过滤器和聚合器。在这种情况下,它是某个字段的总和。不知道有什么方法以及如何拦截它。我会调查更多的帖子发现。
  • 如果你从 VS 2017 的源代码重新编译这个库,那么它是有意义的。描述了导致该问题的 C# 编译器的底层更改here

标签: c# visual-studio-2013 visual-studio-2017 system.reflection


【解决方案1】:

感谢 mike z 为我指明了正确的方向。 我现在正在检查传入的 methodTypes 是否是静态的,如果它是静态的,我现在将 null 作为目标对象传入。但如果它不是静态的,那么我创建对象的一个​​实例并传递它。这是新的调用代码:

var m = ((Func<Type, Type[]>)this.GetType().GetMethod("SumAvgFunc", BindingFlags.Static | BindingFlags.NonPublic)
                        .MakeGenericMethod(proptype).Invoke(null, null)).GetMethodInfo();
                    object obj = null;
                    if (!m.IsStatic)
                    {
                        obj = Activator.CreateInstance(m.DeclaringType);
                    }
                    return GetMethod(aggregate, m, 1, obj).MakeGenericMethod(type);

所以我向 GetMethod() 方法添加了一个参数,该参数接受一个对象,如果该方法是静态的,则该对象将为 null,否则它将是该方法所属的类的实例。这是GetMethod:

private static MethodInfo GetMethod(string methodName, MethodInfo methodTypes, int genericArgumentsCount, object obj)
        {
            var methods = from method in typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static)
                          let parameters = method.GetParameters()
                          let genericArguments = method.GetGenericArguments()
                          where method.Name == methodName &&
                            genericArguments.Length == genericArgumentsCount &&
                            parameters.Select(p => p.ParameterType).SequenceEqual((Type[])methodTypes.Invoke(obj, genericArguments))
                          select method;
            return methods.FirstOrDefault();
        }

现在一切正常,就像以前使用 VS 2013 一样。 谢谢你,迈克 z

【讨论】:

    猜你喜欢
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    相关资源
    最近更新 更多