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.

Reply via email to