Это, кажется, работает прекрасно:
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();
UPDATE
Если вы абсолютно необходимо, вы можете перебрать все регистрации:
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>());
}
}
Грязные, но работает.
Я не понимаю проблему. Почему вы используете 'AutoActivate'? Думаю, вам просто нужно зарегистрировать экземпляр как обычную регистрацию и решить эту проблему. –
Но если ваше представление привязано к вашей ViewModel, не означает ли, что ctor на VM будет вызван, как только вы перейдете к своему представлению, в какой момент MessengerInstance будет знать, что делать с отправляемым сообщением? – Darek
@Darek Навигация асинхронна –