-
-
Save bryanhunter/1127914 to your computer and use it in GitHub Desktop.
// Hooks up Castle Windsor as the container for your Caliburn.Micro application. | |
// Turns on support for delegate factory methods (e.g. passing the factory "Func<XyzEditViewModel>" as a constructor arg) | |
// Dependencies: In addition to Caliburn.Micro you will need to reference Castle.Core and Castle.Windsor | |
public class CastleBootstrapper<TRootViewModel> : Bootstrapper<TRootViewModel> | |
{ | |
private ApplicationContainer _container; | |
protected override void Configure() | |
{ | |
_container = new ApplicationContainer(); | |
_container.AddFacility<TypedFactoryFacility>(); | |
} | |
protected override object GetInstance(Type service, string key) | |
{ | |
return string.IsNullOrWhiteSpace(key) | |
? _container.Resolve(service) | |
: _container.Resolve(key, service); | |
} | |
protected override IEnumerable<object> GetAllInstances(Type service) | |
{ | |
return (IEnumerable<object>)_container.ResolveAll(service); | |
} | |
protected override void BuildUp(object instance) | |
{ | |
instance.GetType().GetProperties() | |
.Where(property => property.CanWrite && property.PropertyType.IsPublic) | |
.Where(property => _container.Kernel.HasComponent(property.PropertyType)) | |
.ForEach(property => property.SetValue(instance, _container.Resolve(property.PropertyType), null)); | |
} | |
} | |
public class ApplicationContainer : WindsorContainer | |
{ | |
public ApplicationContainer() | |
{ | |
Register( | |
Component.For<IWindowManager>().ImplementedBy<WindowManager>().LifeStyle.Is(LifestyleType.Singleton), | |
Component.For<IEventAggregator>().ImplementedBy<EventAggregator>().LifeStyle.Is(LifestyleType.Singleton) | |
); | |
RegisterViewModels(); | |
} | |
private void RegisterViewModels() | |
{ | |
Register(AllTypes.FromAssembly(GetType().Assembly) | |
.Where(x => x.Name.EndsWith("ViewModel")) | |
.Configure(x => x.LifeStyle.Is(LifestyleType.Transient))); | |
} | |
} | |
// If you don't already have a ForEach extension method in your project here you go: | |
public static class ForEachExtension | |
{ | |
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) | |
{ | |
foreach (T element in source) | |
{ | |
action(element); | |
} | |
} | |
} |
HEskandari
commented
Jan 18, 2012
via email
Thanks for the reply.
Yeah I deleted my question after finding the answer in the documentation about SelectAssembly.
Now, you mentioned the container. So if I have say a MenuBuilder that builds up a menu, with menu items, and I set the Action of one of the MenuItem clicks to open up a new window, I resolve that by injecting into this MenuBuilder the ViewModel of this window I want to open? If I get the viewmodel how do I then open up it's corresponding view?
-mark
I'm using Castle Windsor.
In the past using basic MVVM I would give the ViewModel a Show() method on it's interface, that Show() method would then call the Show() of the View, and the IView was injected into the constructor of the ViewModel.
Looked through Payroll solution 1 and 2, couldn't compile probably because of lacking DevEx products.
But I noticed you're using what looks like Caliburn and not Caliburn.Micro as your bootstrapping was done in the App.xaml.cs.
I couldn't find where you fire up a new view or UI in the code in the Payroll part 2 solution. That's really all I need to get to, presenting a new window or view.
Thanks Brian. This is what I was looking for.
Any idea about how the ViewModel release management should be handled?
When I have to show a new window, I am first using Castle's container to resolve the new ViewModel, and then invoking the ShowWindow method of WindowManager to take care of the rest.
But how I can make sure this is released from the container after the window is closed?
Accounting to the document, even though the LifeStyle of view model is set to transient, it's still necessary to invoke Release when the window is closed.
http://docs.castleproject.org/Default.aspx?Page=LifeStyles&NS=Windsor&AspxAutoDetectCookieSupport=1#Transient_5