【问题标题】:TypeLoadException on Attribute in shared assembly共享程序集中的属性上的 TypeLoadException
【发布时间】:2017-11-13 23:39:33
【问题描述】:

11/7 更新 10:29 MST

奇怪的是,如果我将属性从ComponentModel 文件夹移回Common 项目的根目录,则代码可以正常工作。在为 InflowHealth.Common.ComponentModel 命名空间重构所有引用之后,我无法想象什么可能引用旧命名空间。

这几乎就像有一些参考隐藏在某处不是基于代码的,而是运行时和动态的,但我在查看InflowHealthErrorContext 的所有查找结果时肯定看不到它。

11/6 更新 19:33 MST

有趣的是,当我注释掉使用自定义属性继承路由的行并使用默认属性时,它仍然爆炸。更有趣的是,它正在寻找的命名空间InflowHealth.Common.InflowHealthErrorContextAttribute实际上是在我重构它并将其移动到文件夹(和命名空间)ComponentModel之前的旧 FQN。

11 月 6 日 07:42 MST 更新

我相信我已经确定该问题与我用来继承操作的另一个自定义属性有关。像这样将该属性添加到HttpConfiguration

public static void MapInheritedAttributeRoutes(this HttpConfiguration config)
{
    config.MapHttpAttributeRoutes(new InheritanceDirectRouteProvider());
}

该属性的实现非常简单:

public class InheritanceDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
    {
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(true);
    }
}

似乎继承此InflowHealthErrorContext 属性会导致问题,但我不确定问题到底出在哪里。我试过了:

  • 删除Inherited = false,使其可继承。
  • 删除 AllowMultiple = true 只是因为它配置错误。

那些并没有改变错误。


原帖

我在由几个 Web API 应用程序共享的 Common 程序集中有一个非常简单的属性。就这么简单,我就是不知道是什么导致了这个异常。

我已尝试收集有关此的 Fusion 日志,但它没有记录它们。

这是Attribute

using System;

namespace InflowHealth.Common.ComponentModel
{
    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
    public sealed class InflowHealthErrorContextAttribute : Attribute
    {
        // This is a positional argument
        public InflowHealthErrorContextAttribute(string errorContext)
        {
            ErrorContext = errorContext;
        }

        public string ErrorContext { get; }
    }
}

这将用于稍后为过滤器内部完成的自动错误日志记录提供一些额外上下文的路由:

[Authorize(Roles = Roles.ALL_ADMINS)]
[Route("api/ControlPanelApi/PayerClassifications")]
[InflowHealthErrorContext("Error getting payer classifications.")]
public IHttpActionResult GetPayerClassifications(int clientId, bool showAllRows)
{
    return Ok(GetData(payerClassificationManager, clientId, showAllRows));
}

在加载应用程序时,当注册 Web API 路由时,它会失败。这是它的突破口:

GlobalConfiguration.Configure(WebApiConfig.Register);

它抛出了这个异常:

无法从程序集“InflowHealth.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”加载类型“InflowHealth.Common.InflowHealthErrorContextAttribute”。

这是堆栈跟踪:

   at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
   at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
   at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
   at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit)
   at System.Reflection.RuntimeMethodInfo.GetCustomAttributes(Type attributeType, Boolean inherit)
   at System.Attribute.GetCustomAttributes(MemberInfo element, Type type, Boolean inherit)
   at System.Attribute.GetCustomAttribute(MemberInfo element, Type attributeType, Boolean inherit)
   at System.Reflection.CustomAttributeExtensions.GetCustomAttribute[T](MemberInfo element)
   at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.IsValidActionMethod(MethodInfo methodInfo)
   at System.Array.FindAll[T](T[] array, Predicate`1 match)
   at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem..ctor(HttpControllerDescriptor controllerDescriptor)
   at System.Web.Http.Controllers.ApiControllerActionSelector.GetInternalSelector(HttpControllerDescriptor controllerDescriptor)
   at System.Web.Http.Controllers.ApiControllerActionSelector.GetActionMapping(HttpControllerDescriptor controllerDescriptor)
   at System.Web.Http.Routing.AttributeRoutingMapper.AddRouteEntries(SubRouteCollection collector, HttpConfiguration configuration, IInlineConstraintResolver constraintResolver, IDirectRouteProvider directRouteProvider)
   at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<>c__DisplayClass4.<MapAttributeRoutes>b__1()
   at System.Web.Http.Routing.RouteCollectionRoute.EnsureInitialized(Func`1 initializer)
   at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<MapAttributeRoutes>b__0(HttpConfiguration config)
   at System.Web.Http.HttpConfiguration.EnsureInitialized()
   at System.Web.Http.GlobalConfiguration.Configure(Action`1 configurationCallback)
   at InflowHealthPortal.MvcApplication.Application_Start() in Global.asax.cs:line 22

【问题讨论】:

  • GetPayerClassifications 方法是否与InflowHealth.Common.ComponentModel 在同一个命名空间和/或项目中?如果他们在不同的项目中,那么他们使用的是什么框架?
  • @Svek 他们在不同的项目中。它们都以 .NET 4.5 为目标,带有 GetPayerClassifications 的程序集通过项目引用引用属性所在的 Common 程序集。
  • 在构建 MVC 应用程序时检查 .dll 是否存在于输出文件夹中;如果不是,请将属性更改为Copy always
  • @MikePerrenoud 删除 binobj 文件夹并重建。一个流浪的 dll 可能会到处闲逛。您是否还可以提供可用于重现问题的minimal reproducible example?我已经尝试使用您迄今为止提供的内容制作一个最小的项目,但无法得到类似的错误。
  • 我和@Nkosi 在一起 - 我建议运行 ProcMonitor 并查看 实际 加载的 DLL 视觉工作室,可能来自一些旧 bin 或旧参考。

标签: c# .net asp.net-web-api attributes


【解决方案1】:

我建议您删除 binobj 文件夹并重建项目。

这个问题有时会发生在编译项目时没有覆盖的流浪 dll 周围。通常在重命名输出文件时。

过去,当引用不反映对代码和重新编译所做的更改时,执行上述操作对我有用。

Nuget 包有时也会发生同样的情况,这将导致必须删除包并重新安装它才能引用正确的 dll。

【讨论】:

    【解决方案2】:

    InflowHealthErrorContextAttribute 属于 InflowHealth.Common.ComponentModel 命名空间但是错误

    无法加载类型 来自程序集的“InflowHealth.Common.InflowHealthErrorContextAttribute” 'InflowHealth.Common,版本=1.0.0.0,文化=中性, PublicKeyToken=null'。

    表明它在InflowHealth.Common 命名空间中被搜索到。会不会是个问题?

    可能在您引用的Common 程序集的某些过时版本中,属性位于InflowHealth.Common 命名空间中并且代码编译没有错误,但在获取输出文件夹属性的程序集中实际上位于InflowHealth.Common.ComponentModel 命名空间和搜索@ 987654327@ 类型失败。

    【讨论】:

    • 除非对InflowHealth.Common 的所有引用都是项目引用,并且属性构建的所有用法,这个引用还能在哪里炸毁?就像我在最新更新中提到的那样,我也确信它是一些运行时绑定,但是在哪里呢?例如,我没有看到任何 Web.config 引用。这也是我一直在寻找的。​​span>
    • 您能否使用一些反汇编程序检查 Common 程序集,该属性是否实际上位于 InflowHealth.Common 命名空间中?我相信会是这样。那么问题是这个程序集的一些过时版本进入了输出文件夹。您确定在构建发生时将此程序集的正确版本复制到输出文件夹吗?
    【解决方案3】:

    有两种可能的原因:

    Web.Config 指向错误的程序集或程序集编译错误。 首先,您指向错误的程序集:

    'InflowHealth.Common.InflowHealthErrorContextAttribute' from assembly 'InflowHealth.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
    

    应该指向:

    InflowHealth.Common.InflowHealthErrorContextAttribute' from assembly 'InflowHealth.Common.ComponentModel
    

    尝试检查 web.Config 的这一部分:

     <dependentAssembly>
            <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
            <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
    

    或在项目中搜索设置装配位置的位置。

    如果这不能派上用场,请反汇编您的代码并查看它的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-17
      相关资源
      最近更新 更多