【问题标题】:Class cannot be found by reflection when usings are inside namespace and not outside. Why?当 usings 在命名空间内部而不是外部时,无法通过反射找到类。为什么?
【发布时间】:2017-10-15 08:31:24
【问题描述】:

我们有一些处理程序,这些处理程序通过反射在 IoC 中实例化,因为它们不能被引用。这工作得很好,直到我使用 StyleCop 并在命名空间内移动了一些处理程序的使用。突然,我们的算法无法获取特定命令的处理程序。我发现这个看似微不足道的变化确实打破了。

变更前的处理程序:

using System;
using System.Threading;
using System.Threading.Tasks;

using AccessManagement.Common.Configuration;
using AccessManagement.DirectoryServices;
using AccessManagement.Management.AdContact.Commands;
using AccessManagement.Management.AdUser;
using AccessManagement.{NotForYourEyes1};
using AccessManagement.{NotForYourEyes1}.Enums;
using AccessManagement.{NotForYourEyes1}.Extensions;
using AccessManagement.{NotForYourEyes1}.Models;

using Architecture.Core;

using {NotForYourEyes2}.Common;
using {NotForYourEyes2}.Common.Configuration;

namespace AccessManagement.Management.AdContact
{


    [EnableHandler]
    public class MoveAdContactHandler : IHandleRequest<MoveAdContact, AdUserResponse>
    {
        public Task<AdUserResponse> Handle(MoveAdContact request, CancellationToken cancellationToken = new CancellationToken())
        {

修改后的处理程序:

namespace AccessManagement.Management.AdContact
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    using AccessManagement.Common.Configuration;
    using AccessManagement.DirectoryServices;
    using AccessManagement.Management.AdContact.Commands;
    using AccessManagement.Management.AdUser;
    using AccessManagement.{NotForYourEyes1};
    using AccessManagement.{NotForYourEyes1}.Enums;
    using AccessManagement.{NotForYourEyes1}.Extensions;
    using AccessManagement.{NotForYourEyes1}.Models;

    using Architecture.Core;

    using {NotForYourEyes2}.Common;
    using {NotForYourEyes2}.Common.Configuration;

    [EnableHandler]
    public class MoveAdContact2Handler : IHandleRequest<MoveAdContact, AdUserResponse>
    {

向 IoC 容器注册处理程序的算法:

    private static void RegisterBusHandlers(IServiceRegistry serviceRegistry, Func<ILifetime> handlersLifetime)
    {
        var handlerProvider = new HandlerRegistrator((i, t) =>
        {
            serviceRegistry.Register(i, t, handlersLifetime());
        });

        var handlerTypes =
        AppDomain.CurrentDomain
                    .GetAssemblies()
                    .SelectMany(a => a.GetTypes())
                    .Where(t => t.GetCustomAttribute<EnableHandlerAttribute>() != null);

        foreach (var handlerType in handlerTypes)
        {
            handlerProvider.RegisterHandler(handlerType);
        }
    }

总结一下——修改前的handler很好找,修改后的handler根本找不到。这对我和我的团队来说是一种脑筋急转弯。谁能解释一下这种行为吗?

【问题讨论】:

  • 我怀疑它可能有这样的效果。也许 StyleCop 也改变了其他东西?
  • @Evk Nah,就是这个。我发誓。用 git 检查。

标签: c# .net reflection namespaces using


【解决方案1】:

那些using 指令现在将在考虑封闭命名空间之前使用。您可能曾经在 AccessManagement.ManagementAccessManagement 内定位类型,而现在将相同的类型名称解析为由 using 指令声明的命名空间内的类型。

哪些,只有你自己能确定。

例如如果有两种不同的EnableHandlerAttribute 类型,那么您的注册码现在可能正在注册完全不同的类型。

【讨论】:

  • 重读了好几遍,还是没看懂。你能提供一些不同的例子吗?
  • @Evk - 想象有两种类型称为SpongeBob。一个位于AccessManagement.Common.Configuration 内。另一个位于AccessManagement 内。在更改之前,定位到的是AccessManagement 中的那个。更改后,位于AccessManagement.Common.Configuration 内。这是因为以前,搜索首先使用命名空间层次结构,并且只有在到达全局命名空间时才使用位于那里的 using 指令。
  • 但是我们在这里讨论的是通过反射发现类型。我相信在编译代码后没有使用指令这样的事情。更不用说有问题的代码会发现所有程序集中的所有类型,因此在这种情况下应该发现这两种类型。
  • @Evk - 是的,但是如果您使用反射来尝试查找所有实现 IThingy 的类型,并且 IThingy 在您的代码中显示为类型名称,并且 编译过程中获取的特定 IThingy 已更改,您现在将从反射中得到不同的结果。反射代码很少完全没有类型名称。例如。在 Querts 注册码中,假设现在正在使用不同的 EnableHandlerAttribute
  • 所以澄清一下,在这种情况下,您的意思是在不同的命名空间中可能有两个EnableHandlerAttribute,现在在更改后选择了不同的一个。
猜你喜欢
  • 2013-03-30
  • 1970-01-01
  • 2011-10-11
  • 2020-11-22
  • 2010-11-21
  • 2011-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多