yeah, if you match just by name it's good enough (as long as the actual
type can be cast to the type of the dependency, which in your case it can).
K
On 23/12/2011 12:42 AM, Matthew Slane wrote:
Thanks, I got it working.
Quite a few of my ViewModels consume the factory to generate other
ViewModels, so 1 isn't really an option.
This didn't work and I would have ended up littering my factory with
lots of similar methods if it had:
TemplateEditViewModelCommands
CreateTemplateEditViewModelCommands(TemplateEditViewModel
mismatchedArgumentName);
Whilst this did (if the resolved object has a constructor that has an
argument called parentModel that is of a type inherited from
ViewModelBase).
T CreateViewModel<T>(ViewModelBase parentModel) where T :
ViewModelBase;
So Windsor in my case is failing to match by exact type (I'm using
2.5.3). My test projects used the same argument names, so I solved my
problem unknowingly.
Matt
I got it working
2011/12/21 Krzysztof Koźmic <[email protected]
<mailto:[email protected]>>
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]
<mailto:[email protected]>.
To unsubscribe from this group, send email to
[email protected]
<mailto:[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]
<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.