Windsor: Circular reference with generics, and Model-View-Presenter setup...

150 views
Skip to first unread message

Derick Bailey

unread,
Jan 24, 2008, 5:14:04 PM1/24/08
to Castle Project Users
I have a custom IoC container that I built about a year or two ago -
it's worked fairly well for a while, but I have recently started using
Windsor for some of the more advanced features and want to switch
entirely over to Windsor. In order to make this switch, I need to be
able to use my standard Model-View-Presenter setup (or some various of
it), using Windsor to automatically provide my View implementation to
the Presenter that I am asking for.

Here's the issue:

My Presenter Base is defined like this:

public abstract class Presenter<P, V>
where P : Presenter<P, V>
where V : IView<P>

and my View base is defined like this:

public interface IView<P>

obviously, there is a circular reference here - I need to know the
Presenter's type to create the view and i need to know the View's type
to create the Presenter.

My custom IoC tool doesn't have any of the auto-magic dependency
resolution that Windsor has. I would register my view implementation
type and my presenter implementation type in my container, and then
when my contain created an instance of the Presenter, the presenter
would call my contain.resolve for the view that I needed and it would
instantiate that view implementation... not magic dependency
resolution involved, so the circular reference was never an issue. The
view instantiation never tried to instantiate the Presenter type -
only the Presenter type instantiates the View type.

Now step in Windsor - I replaced my contain with Windsor's and
suddenly i'm getting stack overflow exceptions trying to resolve my
Presenter or my View. Try to get the Presenter and it calls
IWindsorContainer.Resolve<IView<MyPresenter>> like it is supposed to.
When this gets called, Windsor sees the <MyPresenter> portion and
tries to resolve the Presenter's instance, which then tries to resolve
the IView<... you get the idea...

The question is:

Can I use this MVP setup with Windsor? If so, what am I doing wrong? I
need to configure Windsor through config files (production app) and
through code (unit tests).

If this isn't possible, can someone point me to a good example of
using windsor to create an MVP setup (and please don't say Monorail -
i'm not using Monorail on this project).

thanks.

Derick Bailey

unread,
Jan 24, 2008, 5:31:35 PM1/24/08
to Castle Project Users
More info... here is the entire definition for my IView<P> interface:

public interface IView<P>
{

P Presenter { get; set; }
}

if I comment out the "P Presenter { get; set; }" line and comment out
the implementation of that property on the class that i'm trying to
test, then things work fine. Why would Windsor read this property and
try to resolve the reference to the presenter? I don't want Windsor to
resolve my property for me... i'm handling that in my code when the
Presenter is instantiated (the presenter assigns itself to the view's
Presenter property).

Victor Kornov

unread,
Jan 24, 2008, 6:00:58 PM1/24/08
to Castle Project Users
> Why would Windsor read this property and try to resolve the reference to the presenter?

That's a feature. Properties with setters are considered an optional
dependency.

The simplest thing to fix you problem is to change IView interface
like this:

public interface IView<P>
{
P Presenter { get; }
void SetPresenter(P presenter);
}

Derick Bailey

unread,
Jan 25, 2008, 9:27:25 AM1/25/08
to Castle Project Users
is there any way to turn that "feature" off?

I don't like that kind of auto-magic "convention over configuration"
stuff.

Derick Bailey

unread,
Jan 25, 2008, 9:31:20 AM1/25/08
to Castle Project Users
... i hit the send button to soon...

i really don't want to change my interface like you suggest because it
implies a semantic coupling between the interface and the implementor
- the developer implementing the interface has to know that the
SetPresenter method needs to set a local var that is returned from the
Presenter property. We can argue back and forth all day, on whether or
not this is obvious or a good / bad thing... point it - i don't like
it and don't want to introduce that kind of required "you have to know
to do this..." code into my projects.

Derick Bailey

unread,
Jan 25, 2008, 10:03:11 AM1/25/08
to Castle Project Users
this "feature" is really starting to make me mad, now.

I have a public virtual property on my Presenter base class, to expose
the View to my code. it has a protected setter:

public virtual V View
{
get { return _view; }
protected set { _view = value; }
}

the protected setter causes Windsor (RC3) to throw an Object Reference
exception... not my code... not my unit tests... Windsor itself throws
an Object Reference exception.

Error 1 TestCase
'DigitalLogbook.UnitTests.PresenterBase.PresenterBaseTestFixture.EmptyPresenterConstructorAutomaticallyRetrievesPresenter'
failed: System.NullReferenceException : Object reference not set to an
instance of an object.
at
Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.SetUpProperties(Object
instance, CreationContext context)
at
Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext
context)
at
Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext
context)
at
Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext
context)
at
Castle.MicroKernel.Lifestyle.SingletonLifestyleManager.Resolve(CreationContext
context)
at
Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext
context)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler
handler, Type service, IDictionary additionalArguments)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler
handler, Type service)
at Castle.MicroKernel.DefaultKernel.get_Item(Type service)
at Castle.Windsor.WindsorContainer.Resolve(Type service)
at Castle.Windsor.WindsorContainer.Resolve[T]()
at
DigitalLogbook.UnitTests.PresenterBase.PresenterBaseTestFixture.EmptyPresenterConstructorAutomaticallyRetrievesPresenter()
in X:\SigmaDelta\Trunk\Code\SigmaDelta\SigmaDelta.UnitTests\MVP
\PresenterBaseTestFixture.cs:line 41 X:\SigmaDelta\Trunk\Code
\SigmaDelta\SigmaDelta.UnitTests\MVP\PresenterBaseTestFixture.cs 41

josh robb

unread,
Jan 25, 2008, 10:05:27 AM1/25/08
to castle-pro...@googlegroups.com
Derick,

Is is possible for you to put together a really simple project which
demonstrates the problem?

If you can either attach it to a JIRA issue or put it up somewehere I
can download it then I'll take a look at this for you.

j.

Ayende Rahien

unread,
Jan 25, 2008, 10:05:54 AM1/25/08
to castle-pro...@googlegroups.com
You need to unregister PropertiesDependenciesModelInspector

foreach(IContributeComponentModelConstruction contributer in kernel.ComponentModelBuilder.Contributors)
{
    if( contributer is PropertiesDependenciesModelInspector)
        kernel.ComponentModelBuilder.RemoveContributer(contributer);

Derick Bailey

unread,
Jan 25, 2008, 10:06:07 AM1/25/08
to Castle Project Users
...

although it may not sound like it, so far... i really do want to use
Windsor... my custom IoC Container doesn't have all the features i
want, and i don't want to re-write what's already been done in a tool
like Windsor. On top of that, I've tried other IoC tools like
Sprint.NET and StructureMap and i don't like any of them - they are
complicated to configure and difficult to use.

I've had great luck with my previous use of Windsor (very limited use,
though), and I really want to understand what's going on here and why
i'm having so many problems, so that I can get my system up and
running with the right toolset.

Ayende Rahien

unread,
Jan 25, 2008, 10:06:21 AM1/25/08
to castle-pro...@googlegroups.com
Take into account that this is a fairly invasive operation and it can break code that expect its properties to be set.

Derick Bailey

unread,
Jan 25, 2008, 10:25:25 AM1/25/08
to Castle Project Users
Josh,

I've created a bug report with attachment in Castle's Jira:

http://support.castleproject.org/browse/IOC-117

The file i uploaded is my actual project, with all my domain objects,
web site, etc. stripped out of it... there is one test fixture with
one unit test in it, to show the exception that i'm getting.

thanks.

Victor Kornov

unread,
Jan 25, 2008, 10:57:41 AM1/25/08
to Castle Project Users
Is it possible to enhance Windsor configuration with some custom
attribute, setting which will cause
PropertiesDependenciesModelInspector to skip property/object instance?

May be custom facility?

Ayende Rahien

unread,
Jan 25, 2008, 11:01:07 AM1/25/08
to castle-pro...@googlegroups.com
Yes, it is possible.
I actually think we have something like that, but I don't recall what exactly

Roelof Blom

unread,
Jan 25, 2008, 12:59:59 PM1/25/08
to castle-pro...@googlegroups.com
It's the [DoNotWire] attribute (Castle.Core), setting the attribute on the Presenter.View and View.Presenter property will fix this Derick's problem.

josh robb

unread,
Jan 26, 2008, 7:29:30 AM1/26/08
to castle-pro...@googlegroups.com
On Jan 25, 2008 5:59 PM, Roelof Blom <roelo...@gmail.com> wrote:
> It's the [DoNotWire] attribute (Castle.Core), setting the attribute on the
> Presenter.View and View.Presenter property will fix this Derick's problem.

Nice one Roelof! Exactly.

josh robb

unread,
Jan 26, 2008, 7:38:48 AM1/26/08
to castle-pro...@googlegroups.com
On Jan 25, 2008 3:03 PM, Derick Bailey <derick...@gmail.com> wrote:
>
> this "feature" is really starting to make me mad, now.

Derick - this "feature" (autowiring) is one of the key ideas which
underlies the whole point of Windsor. If we wanted another Spring.Net
with 1000's of lines of XML config explicitly stating what components
should be wired where - then Windsor wouldn't exist.

I realise that learning new tools can be frustrating (I well recall
feeling this when I was getting started) - but Windsor/Microkernel is
_extremely_ customizable. Any default behaviour can be changed by
writing a facility/inspector/whatever.

Criticizing a very well designed and production tested container is
probably not the best way to encourage the people who spend their own
time working on it to help you.

Asking questions about why things have been designed the way they have
- is much more likely to help you grok how to do things the Castle
Windsor way.

j.

Derick Bailey

unread,
Jan 28, 2008, 9:37:54 AM1/28/08
to Castle Project Users
Josh,

You have some good points there, and I apologize for the my previous
comments. I let my frustration get the better of me in that situation,
since i didn't understand why things were not working the way i
expected them to. I'll make sure to keep that in check, in the future.

On Jan 26, 6:38 am, "josh robb" <josh_r...@fastmail.fm> wrote:

josh robb

unread,
Jan 28, 2008, 9:47:15 AM1/28/08
to castle-pro...@googlegroups.com
Thanks!

;)

Reply all
Reply to author
Forward
0 new messages