Reputation: 8981
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
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
..
Upvotes: 0
Views: 224
Reputation: 574
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.
Upvotes: 1