Wcf Facility (server) can not correctly resolve open generic decorators

50 views
Skip to first unread message

Adam Langley

unread,
May 7, 2011, 2:24:33 AM5/7/11
to castle-pro...@googlegroups.com
Dear Castle groups,
 
I have a WCF service which has a single constructor dependency - this dependency is 'generically decorated'.
 
i.e. its constructor looks like this:
 

public ServiceGenericDependency(IDecorator<IServiceNoDependencies> arg2)

{

}

 

My 'decorator' constructor looks like this:

public Decorator(T arg)

{

}

Castle has the typeof(IDecorator<>) registration, and the typeof(IServiceNoDependencies) registered.

PROBLEM: The WCF Facility fails to create the server.
IF I add a default constructor to my decorator class, then everything works.
IF I resolve the WCF service on the server (as a local component, i.e. take WCFFacility out of the equation) then everything works.

I have included a test program below - just reference WcfFacility + Castle. This is quite an urgent issue for me.

Thank you!

using Castle.Windsor;
using Castle.MicroKernel.Registration;
using Castle.Facilities.WcfIntegration;
using System.ServiceModel;

namespace DecoratorChains
{
    class Program
    {
        static IWindsorContainer container;
        static void Main(string[] args)
        {
            container = new WindsorContainer()
                .AddFacility<WcfFacility>();

            // this is my decorator, it is capable of decorating any service.
            container.Register(Component.For(typeof(IDecorator<>)).ImplementedBy(typeof(Decorator<>)));

            container.Register(
                Component.For<IServiceGenericDependency>().ImplementedBy<ServiceGenericDependency>().LifeStyle.Transient
                        .AsWcfService(new DefaultServiceModel().AddEndpoints(
                                WcfEndpoint.BoundTo(new NetTcpBinding())
                                    .At("net.tcp://localhost/Operations")
                                )
                        )
            );

            // this is my service that WILL BE decorated, then used as a constructor argument.
            container.Register(Component.For<IServiceNoDependencies>().UsingFactoryMethod(() => new ServiceNoDependencies()));
           

            var client = ChannelFactory<IServiceGenericDependency>.CreateChannel(
                new NetTcpBinding(), new EndpointAddress("net.tcp://localhost/Operations"));

            // this passes
            var cc = container.Resolve<IServiceGenericDependency>();
           
            // this fails
            client.DoSomething();
        }

    }

    interface IServiceNoDependencies
    {
    }

    class ServiceNoDependencies : IServiceNoDependencies
    {
    }

    interface IDecorator<T>
    where T : class
    {
    }

    class Decorator<T> : IDecorator<T>
        where T : class
    {
        /// <summary>
        /// Remove this constructor and all tests will pass
        /// </summary>
        /// <param name="arg"></param>
        public Decorator(T arg)
        {
        }
    }

    [ServiceContract]
    interface IServiceGenericDependency
    {
        [OperationContract]
        void DoSomething();
    }

    class ServiceGenericDependency : IServiceGenericDependency
    {
        public ServiceGenericDependency(IDecorator<IServiceNoDependencies> arg2)
        {
        }

        public void DoSomething()
        {

        }
    }
}

 

Craig Neuwirt

unread,
May 10, 2011, 3:52:40 PM5/10/11
to castle-pro...@googlegroups.com, krzy...@kozmic.pl
Adam,

  I believe the problem relates to the open-generic registration.  The Wcf Facility waits for the service to be in the ready state before it opens the host.  In this case, the container shows the ServiceGenericDependency component as waiting for the IDecorator dependency.  It would be nice for the container to handle this properly.  I have seen this before and added an option to open the service host eagerly.  This will not wait for the component to be reported as valid before opening the host.  In your example, it resolved the issue

var wcfFacility=XXXX
wcfFacility.Services.OpenServiceHostsEagerly = true;

cheers,
  craig


--
You received this message because you are subscribed to the Google Groups "Castle Project Users" group.
To post to this group, send email to castle-pro...@googlegroups.com.
To unsubscribe from this group, send email to castle-project-u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/castle-project-users?hl=en.

Adam Langley

unread,
May 10, 2011, 6:16:54 PM5/10/11
to castle-pro...@googlegroups.com, krzy...@kozmic.pl
Hi Craig,

Thanks for that - I will give it a try ASAP.
I thought it might be something like this - I noticed that when I forced a local resolution to occur, then a final 'ComponentRegistered' event was fired, which reported a 'closed generic' component... specialized to the generic argument (so in this case, IDecorator<IServiceNoDependencies>) - but it was not added to the list of 'registered components'.
I dont know enough about Castle to comprehend what kind of lifecycle is going on under the hood - it would be ideal if the WCF facility was able to open hosts for these components without 'eager' resolution.

Thanks for the help Craig,

Adam Langley


 Please consider the environment before printing this email!

Krzysztof Koźmic

unread,
May 10, 2011, 6:21:10 PM5/10/11
to castle-pro...@googlegroups.com, krzy...@kozmic.pl

Can you provide a failing test with the reproduction

Adam Langley

unread,
May 10, 2011, 10:48:54 PM5/10/11
to castle-pro...@googlegroups.com
Hi Krzysztof

Yes I will do that tonight - I will try to base it on the WcfFacility.Tests code and will email it.
I have seen mention before of git push/pull something-or-other but I have never done it before so I will stick to email unless someone can send me a link on how to send my test code straight to git?

Thank you
Adam Langley


 Please consider the environment before printing this email!

Krzysztof Koźmic

unread,
May 10, 2011, 11:20:00 PM5/10/11
to castle-pro...@googlegroups.com

Adam Langley

unread,
May 11, 2011, 5:28:39 PM5/11/11
to castle-pro...@googlegroups.com
I have created a git account, but there was some kind of problem when I clicked "fork" on the Wcf page - it says I have a fork in my repository, but when I click it I just get "404, this is not the page you are looking for", indicating something has gotten corrupted - which is odd considering it only took me 3 or 4 clicks to do it!
I have posted a question to the admins but turnaround seems to take several hours - has anyone else had a similar experience?

Thanks

Adam Langley

 Please consider the environment before printing this email!

Craig Neuwirt

unread,
May 12, 2011, 8:34:12 AM5/12/11
to castle-pro...@googlegroups.com, krzy...@kozmic.pl
Adam/Krzysztof,

I added an ignore test to demonstrate the problem with open-generics. It is just Adams example for the most part.

Nimble

unread,
May 12, 2011, 3:24:41 PM5/12/11
to castle-pro...@googlegroups.com
Thanks Craig!
(still waiting to hear from GitHub)

Best regards
Adam Langley

Sent from my iPhone

Reply all
Reply to author
Forward
0 new messages