The problem is your signatures don't match.
Windsor will try to match inline dependencies by name and then if that
fails by (exact) type.
Your factory defines the argument as
ViewModelBase parentModel
but the TemplateEditViewModelCommands defines its dependency as
TemplateEditViewModel parentViewModel
As you can see, neither is matching therefore Windsor will not use the
agument you're providing, trying to get the dependency from the
container itself, which it's also unable to do, because that'd cause a
cycle, hence the exception.
Two solutions to that:
1. don't abuse factories - pass the dependency right into the object
rather than using factory in the constructor.
2. Make sure the names and/or types align between the factory and the
TemplateEditViewModelCommands
K
On 22/12/2011 12:22 AM, Matthew Slane wrote:
Hi,
I can't really break the cycle as I can't see why it should be cyclic.
I set my app up like so in the constructor of the main window.
_container = new WindsorContainer();
_container.Install(
FromAssembly.Containing<TemplateEngineViewModel>()
);
this.DataContext =
_container.Resolve<TemplateEngineViewModel>();
Ctor of TemplateEngineViewModel:
public TemplateEngineViewModel(IViewModelFactory factory)
{
_factory = factory;
_editorViewModel =
_factory.CreateViewModel<TemplateEditViewModel>();
}
Ctor of TemplateEditViewModel:
public TemplateEditViewModel(IViewModelFactory factory)
{
_factory = factory;
_commands =
_factory.CreateViewModel<TemplateEditViewModelCommands>(this); //fails
here, "this" doesn't get respected, a new instance of
TemplateEditViewModel gets created instead.
}
and then:
public TemplateEditViewModelCommands(TemplateEditViewModel
parentViewModel, IViewModelFactory factory)
{
_parent = parentViewModel;
_factory = factory;
}
my Installer is simply.
IFacility[] facilities = container.Kernel.GetFacilities();
if(facilities.Where(x => x.GetType() ==
typeof(TypedFactoryFacility)).Count() == 0)
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<IViewModelFactory>().AsFactory()
AllTypes.FromThisAssembly().BasedOn<ViewModelBase>()
);
The error message is:
Castle.MicroKernel.CircularDependencyException was unhandled by user code
Message=A cycle was detected when trying to resolve a dependency.
The dependency graph that resulted in a cycle is:
- Service dependency 'parentViewModel' type
'TemplateEngineGUILib.ViewModels.EditViewModel' for Void
.ctor(TemplateEngineGUILib.ViewModels.TemplateEditViewModel,
TemplateEngineGUILib.IViewModelFactory) in type
TemplateEngineGUILib.ViewModels.TemplateEditViewModelCommands
+ Service dependency 'parentViewModel' type
'ExcelTemplateEngineGUILib.ViewModels.TemplateEditViewModel' for Void
.ctor(TemplateEngineGUILib.ViewModels.TemplateEditViewModel,
TemplateEngineGUILib.IViewModelFactory) in
TemplateEngineGUILib.ViewModels.TemplateEditViewModelCommands
As I said, if I take all these constructors and create new classes
around them in a new project with the same configuration, it works fine.
Thanks,
Matt
2011/12/21 Krzysztof Koźmic <[email protected]
<mailto:[email protected]>>
Matt,
First of all inspect what the cycle is, and why it appears. Can
you break it?
If not, think about what would you do differently if you were
building the graph by hand.
If you then can share those details we will be able to assist you
further.
cheers,
Krzysztof
On 21/12/2011 10:38 PM, Matt wrote:
Hi,
I'm struggling to resolve a circular dependency issue. I'm using
Castle to resolve view models in an MVVM project and some view
models
have a child parent relationship. All my view models inherit from
ViewModelBase.
I have a factory interface:
public interface IViewModelFactory
{
T CreateViewModel<T>() where T : ViewModelBase;
T CreateViewModel<T>(ViewModelBase parentModel) where T :
ViewModelBase;
}
I have a basic installer which simply registers the factory
interface
and also all types based on ViewModelBase
Every time I try to call something like
var commands =
factory.CreateViewModel<TemplateCommandsViewModel>(this);
I get a circular dependency exception.
However when I stripped the code down to purely the IOC stuff and
moved it to a different project it works fine.
When I watch the constructors in the debugger, instead of passing
"this" through to the constructor, a new instance is created.
Being relatively new to Castle, I am absolutely clueless as to
where
to start on this one. Any ideas?
Thanks,
Matt
--
You received this message because you are subscribed to the Google
Groups "Castle Project Users" group.
To post to this group, send email to
[email protected]
<mailto:[email protected]>.
To unsubscribe from this group, send email to
[email protected]
<mailto:castle-project-users%[email protected]>.
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.
--
You received this message because you are subscribed to the Google
Groups "Castle Project Users" group.
To post to this group, send email to
[email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.
--
You received this message because you are subscribed to the Google Groups "Castle
Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.