Qerts
Qerts

Reputation: 1005

Class cannot be found by reflection when usings are inside namespace and not outside. Why?

We have some handlers, these handlers are instantiated in IoC by reflection because they cannot be referenced. This worked just fine until I came with StyleCop and moved usings of some handlers inside the namespace. Suddenly, our algorithm could not get handler for the particular command. I found out that this seemingly insignificant change did the break.

Handler before change:

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())
        {

Handler after change:

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>
    {

Algorithm registering handler to IoC container:

    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);
        }
    }

To summarize -- handler before the change is found well, handler after the change is not found at all. This is sort of brain twister for me and my team. Can anyone explain this behavior please?

Upvotes: 1

Views: 185

Answers (1)

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239704

Those using directives will now be used before considering enclosing namespaces. You presumably used to be locating types inside either AccessManagement.Management or AccessManagement and are now instead resolving the same type names to type(s) within the namespaces declared by those using directives.

Which ones, only you can determine.

E.g. if there are two different EnableHandlerAttribute types then your registration code may now be registering completely different types now.

Upvotes: 4

Related Questions