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.

Reply via email to