我有一个简单的框架,该框架将允许“一切”订阅事件,前提是已传递“警卫队”。声明它的语法如下:
public class MyObject : ICanHandle<MySuperAwesomeEvent, GivenYouAreLeetGuard> { .... }
可以通过两种不同方式创建防护。通过使用此扩展方法在容器中注册
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);
}
或者它将通过解析在我的框架中的组件期间创建。
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);
}
在我的应用程序中运行此程序符合我的预期,但是在我的测试中,我无法解决任何“防护措施”。
[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);
}
}
IComponentContext中的TryResolveNamed
方法将永远找不到我的注册后卫。看着调试器,我可以清楚地看到“某物”是以某种方式注册的
我在这里做错了什么?有关如何改进代码的其他建议也附有评论。谢谢!
编辑:
在调试单元测试期间,我尝试通过在Visual Studio的“模拟”窗口中键入以下命令来检查是否已注册Guard,
lifeTimeScope.IsRegisteredWithName("Caliburn.Micro.Demo.Tests.MustBeAdminGuard",typeof(MustBeAdminGuard))
此查询返回true。通过传递IComponentContext
而不是ILifeTimeScope
的真正区别是什么?我以为该接口只公开了ILifeTimeScope
公开的方法的子集。
答案 0 :(得分:0)
我自己进行了类似的测试,并且可以正常工作,但是我知道您的问题在哪里,您已经注册了MustBeAdminGuard类型,并且您想解析其他类型的IExecuteGuard,所以不要指望它会像这样工作:)
因此,要解决此问题,您必须更改RegisterCommandGuard类中的注册部分。您有两种可能性选择想要的
//1. looks better
builder.RegisterType<TCommandGuard>().Named<IExecuteGuard>(typeName);
//2.
builder.RegisterType<TCommandGuard>().Named(typeName, typeof(IExecuteGuard));
让我知道它是否可以解决您的问题,必须^^,因为我已经在常见示例中对其进行了测试。