使用Autofac立即创建ViewModel实例
本文关键字:ViewModel 实例 创建 Autofac 使用 | 更新日期: 2023-09-27 18:28:22
我将用Autofac替换MVVM Light默认的SimpleIOC。到目前为止还不错,但现在我正试图在应用程序启动后立即初始化一个ViewModel,因为我需要用MessengerInstance
和SimpleIOC注册一些调用,这和SimpleIoc.Default.Register<MyViewModel>(true);
一样简单,但我找不到使用Autofac的方法。
我尝试了初始化ViewModel的containerBuilder.RegisterType<MyViewModel>().AutoActivate();
,但当我需要它进行绑定时,它没有注册:
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);
这似乎运行得很好:
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;
}
}
你必须使用自动激活吗?换句话说,在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 . . .
如果您需要在启动时运行一些代码,请考虑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>());
}
如果你的ViewModels实现了一个基类,你可以使用:
foreach (var r in container.ComponentRegistry.Registrations)
{
if (r.Target.Activator.LimitType.IsSubclassOf(typeof (ViewModel)))
{
var dump = container.ResolveComponent(r, Enumerable.Empty<Parameter>());
}
}
脏,但有效。