我用 Autofac 替换MVVM Light默认 SimpleIOC 。到目前为止一切都那么好,但现在我尝试在应用程序启动时尽快初始化一个ViewModel,因为我需要使用MessengerInstance
注册一些调用,而SimpleIOC就像SimpleIoc.Default.Register<MyViewModel>(true);
一样简单,但我无法通过Autofac找到方法。
我尝试containerBuilder.RegisterType<MyViewModel>().AutoActivate();
初始化ViewModel但是当我需要它进行绑定时它没有注册:
containerBuilder.RegisterType<MyViewModel>().AutoActivate();
...
public MyViewModel MyVM
{
get { return this.container.Resolve<MyViewModel >(); } //<- Boom! ComponentNotRegisteredException!!
}
修改
问题是我希望在解决之前激活ViewModel,因为我在那里注册了一条消息:
public MyViewModel()
{
MessengerInstance.Register<bool>(this,(b) => DoThisAction(b));
}
如果此时未注册ViewModel,则消息将丢失:
//MyView is binded to MyViewModel
NavigationService.NavigateTo("MyView);
MessengerInstance.Send<bool>(true);
答案 0 :(得分:3)
这似乎完全正常:
internal class Program
{
public static IContainer container;
public MyViewModel MyVM
{
get { return Program.container.Resolve<MyViewModel>(); }
}
private static void Main(string[] args)
{
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<MyViewModel>();
container = containerBuilder.Build();
Program p = new Program();
MyViewModel vm = p.MyVM;
}
}
您是否必须使用AutoActivate?换句话说,您是否需要在Build事件中完成构造函数?
来自Autofac文档:
自动激活组件是一个只需要的组件 在容器构建时激活一次。这是一个“热情的开始” 没有调用组件上的方法的行为方式 接口需要实现 - 组件的单个实例 将在不参考所持实例的情况下解决。
所以对我来说,如果你使用AutoActivation,注册类型将不会保存在构建器注册表中,因此你必须重新注册它。
如果你绝对需要,那么必须注册两次:
internal class Program
{
public static IContainer container;
public MyViewModel MyVM
{
get { return Program.container.Resolve<MyViewModel>(); }
}
private static void Main(string[] args)
{
ContainerBuilder containerBuilder = new ContainerBuilder();
Console.WriteLine("Before register");
containerBuilder.RegisterType<MyViewModel>().AutoActivate();
containerBuilder.RegisterType<MyViewModel>();
container = containerBuilder.Build();
Program p = new Program();
Console.WriteLine("Before property retrieval");
MyViewModel vm = p.MyVM;
}
}
internal class MyViewModel
{
public MyViewModel()
{
Console.WriteLine("MyViewModel");
}
}
结果:
Before register
MyViewModel
Before property retrieval
MyViewModel
Press any key to continue . . .
如果您需要运行一些code at startup, consider IStartable:
public class StartupMessageWriter : IStartable
{
public void Start()
{
Console.WriteLine("App is starting up!");
}
}
....
var builder = new ContainerBuilder();
builder
.RegisterType<StartupMessageWriter>()
.As<IStartable>()
.SingleInstance();
<强>更新强>
如果你绝对必须,你可以遍历所有注册:
foreach (var r in container.ComponentRegistry.Registrations)
{
var dump = container.ResolveComponent(r, Enumerable.Empty<Parameter>());
}
如果您的ViewModel实现了基类,您可以使用:
foreach (var r in container.ComponentRegistry.Registrations)
{
if (r.Target.Activator.LimitType.IsSubclassOf(typeof (ViewModel)))
{
var dump = container.ResolveComponent(r, Enumerable.Empty<Parameter>());
}
}
很脏,但有效。