0

I have a simple framework which will allow "everything" subscribe to events given that a "Guard" has been passed. The syntax for declaring it looks like this:

public class MyObject : ICanHandle<MySuperAwesomeEvent, GivenYouAreLeetGuard> { .... }

The guard can be created two different ways. Either by registering in the container using this extensions method

public static void RegisterCommandGuard<TCommandGuard>(this ContainerBuilder builder)
  where TCommandGuard : IExecuteGuard
 {
     var type = typeof(TCommandGuard);
     var typeName = type.FullName;
     builder.RegisterType<TCommandGuard>().Named(typeName, type);
 }

Or it will be created by using reflection during the resolvement of this component in my framework.

public bool CanExecute(object message)
{
    object resolvedType = null;
    var name = CanExecuteGuard.FullName;
    if(!_componentContext.TryResolveNamed(name, typeof(IExecuteGuard), out resolvedType))
    {
        try
        {
            resolvedType = (IExecuteGuard)Activator.CreateInstance(CanExecuteGuard);
        }
        catch (Exception e)
        {
            throw new Exception($"Cannot locate {name} in container nor create an instance of it. See inner exception:", e);
        }
    }

    return ((IExecuteGuard)resolvedType).CanExecute(message);
}

Running this in my application works as I expect, but in my tests I'm not able to resolve any of the "Guards".

[Fact]
public void EventAggregator_GivenGuardWithDependencies_ShouldFireEventToAllSubscribers()
{
    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterType<UserRepository>().As<IUserRepository>();
    containerBuilder.RegisterCommandGuard<MustBeAdminGuard>();
    var container = containerBuilder.Build();

    using (var lifeTimeScope = container.BeginLifetimeScope())
    {
        var eventAggregator = new ExtendedEventAggregator(lifeTimeScope);
        var @object = new ObjectWhichHandlesUsers();
        eventAggregator.Subscribe(@object);
        eventAggregator.PublishOnUIThread(new FireEmployeeCommand(userId: 1, userToFireId: 5));
        @object.UserIds.Should().HaveCount(6);
    }
}

The TryResolveNamed method in the IComponentContext will never find my registered guard. Looking at the debugger, I can clearly see that "something" is registered somehow

enter image description here

What am I doing wrong here? Other suggestions on how to improve the code is also appricated with a comment. Thanks!

EDIT:

During debugging of my unit test, I tried to check wheter or not the Guard had been registered by typing the following in the Immidiate Window in Visual Studio:

lifeTimeScope.IsRegisteredWithName("Caliburn.Micro.Demo.Tests.MustBeAdminGuard",typeof(MustBeAdminGuard))

And this query returns true. What is the real difference by passing in the IComponentContext instead of the ILifeTimeScope? I thought this interface only exposed a subset of the methods exposed by ILifeTimeScope..

1 Answer 1

1

i have test smth similar on my own, and it is working, but i know where is your problem, you have registered type MustBeAdminGuard and you want to resolve different type IExecuteGuard, so don't expect that it will work like this :)

So to solve it you have to change registering part in class RegisterCommandGuard. You have two possibilities choose which you want

//1. looks better
builder.RegisterType<TCommandGuard>().Named<IExecuteGuard>(typeName);

//2.
builder.RegisterType<TCommandGuard>().Named(typeName, typeof(IExecuteGuard));

Let me know if it solved your problem, it have to ^^, since i have tested it on common example.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.