Created
August 5, 2011 16:29
-
-
Save bryanhunter/1127914 to your computer and use it in GitHub Desktop.
Castle bootstrapper for Caliburn.Micro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} | |
} | |
} |
Main window has a ViewModel that is derived from PresenterManager, this
class knows how to display ViewModels. In ShellViewModel you just call this
method on base class (also there's an extension method) to display your
ViewModel. There isn't very difference between Caliburn or Caliburn.Micro
in this sense. *
*
…On Thu, Jan 19, 2012 at 12:43 AM, Mark Wilkinson < ***@***.*** > wrote:
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.
---
Reply to this email directly or view it on GitHub:
https://gist.github.com/1127914
If you register components by instance, it probably means the component
uses singleton lifestyle, but you alraedy have an instance of the component
that you want to use. So I'd register it using:
container.Register(Component.For<IMyService>().Instance(myserviceInstance).LifeStyle.Singleton);
So now that you have the interface and registered it as singleton, you can
inject it into ctor/property as before. If you are registering multiple
classes with the same interface but with different name (not sure if that
is even possible in Windsor) there are other tricks you can use to decide
on runtime which implementation of the interface you want to resolve.
In general, having direct dependency to container and using Resolve method
everywhere is something you probably want to avoid.
…On Sat, Jan 21, 2012 at 2:07 AM, Mark Wilkinson < ***@***.*** > wrote:
To Bryan or Hadi,
How do I get to the container to resolve something myself? If I Register
a dependency in Windsor with the .Named("someName") how do I get back to
the container to resolve that instance?
---
Reply to this email directly or view it on GitHub:
https://gist.github.com/1127914
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.