使用Autofac立即创建ViewModel实例

时间:2014-10-29 15:08:26

标签: c# .net dependency-injection mvvm-light autofac

我用 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);

1 个答案:

答案 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>());
    }
}

很脏,但有效。