Windsor component registration with generic factory methods?

1,511 views
Skip to first unread message

npinski

unread,
May 11, 2012, 2:27:35 PM5/11/12
to Castle Project Development List
Hi there,

Is there a way to register a WindsorContainer to resolve a generic
type using a generic factory method?

I know I can do registration like:
Component.For<IMyService>().ImplementedBy<MyServiceImpl>()
and
Component.For<MyObject>().UsingFactoryMethod(MyObjectFactory.Create)
and even
Component.For(typeof(IMyGenericService<>)).ImplementedBy(typeof(MyGenericServiceImpl<>))

what I'm looking for is something like:
Component.For(typeof(MyGenericObject<>)).UsingFactoryMethod(MyGenericObjectFactory.Create<>())

Is there a way to do this in a clean way? I started peripherally
reading about IGenericImplementationMatchingStrategy, and Typed
Factory Facilities, but this seems like overkill for what I'm doing.

The workaround I have right now is to create a wrapper for
MyGenericObject<>, and have an interface for the wrapper, which I can
then register with the aforementioned syntax
Component.For(typeof(IMyGenericService<>)).ImplementedBy(typeof(MyGenericServiceImpl<>))



Thanks in advance, guys!

Krzysztof Koźmic

unread,
May 11, 2012, 6:45:02 PM5/11/12
to castle-pro...@googlegroups.com
You can but since c# doesn't support that your factory method would have
to do some reflection.

@K

npinski

unread,
May 14, 2012, 6:54:58 PM5/14/12
to Castle Project Development List
That's fine. But i'm not sure I understand...what kind of signature
would the configuration have to have? I assume you are implying the
type of the generic parameter would need to be passed in to the
factory method?

On May 11, 3:45 pm, Krzysztof Koźmic <krzysztof.koz...@gmail.com>
wrote:
> You can but since c# doesn't support that your factory method would have
> to do some reflection.
>
> @K
>
> On 12/05/2012 4:27 AM, npinski wrote:
>
>
>
>
>
>
>
> > Hi there,
>
> > Is there a way to register a WindsorContainer to resolve a generic
> > type using a generic factory method?
>
> > I know I can do registration like:
> > Component.For<IMyService>().ImplementedBy<MyServiceImpl>()
> > and
> > Component.For<MyObject>().UsingFactoryMethod(MyObjectFactory.Create)
> > and even
> > Component.For(typeof(IMyGenericService<>)).ImplementedBy(typeof(MyGenericSe rviceImpl<>))
>
> > what I'm looking for is something like:
> > Component.For(typeof(MyGenericObject<>)).UsingFactoryMethod(MyGenericObject Factory.Create<>())
>
> > Is there a way to do this in a clean way?  I started peripherally
> > reading about IGenericImplementationMatchingStrategy, and Typed
> > Factory Facilities, but this seems like overkill for what I'm doing.
>
> > The workaround I have right now is to create a wrapper for
> > MyGenericObject<>, and have an interface for the wrapper, which I can
> > then register with the aforementioned syntax
> > Component.For(typeof(IMyGenericService<>)).ImplementedBy(typeof(MyGenericSe rviceImpl<>))
>
> > Thanks in advance, guys!

Krzysztof Koźmic

unread,
May 15, 2012, 5:59:25 AM5/15/12
to castle-pro...@googlegroups.com
yes

Nik Pinski

unread,
May 17, 2012, 3:35:13 AM5/17/12
to castle-pro...@googlegroups.com
Could you be a little more clear?  This really isn't much to go on, and while I understand conceptually the kind of reflection the factory method would have to do, I don't understand how to register the generic MyGenericObject<T> where T is passed in to the factory method...

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




--
Nik.

Krzysztof Koźmic

unread,
May 17, 2012, 4:07:07 AM5/17/12
to castle-pro...@googlegroups.com
.UsingFactoryMethod((k,m,c) => YourFactory(m.Implementation));
yes
To post to this group, send email to castle-pro...@googlegroups.com.
To unsubscribe from this group, send email to castle-project-d...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/castle-project-devel?hl=en.




--
Nik.

--
You received this message because you are subscribed to the Google Groups "Castle Project Development List" group.
To post to this group, send email to castle-pro...@googlegroups.com.
To unsubscribe from this group, send email to castle-project-d...@googlegroups.com.

npinski

unread,
Jun 7, 2012, 6:50:07 PM6/7/12
to Castle Project Development List
Hey Krzystof, your last reply got caught in my spam filter for some
reason.

I just tried this syntax and unfortunately now I get the following
exception (even before "YourFactory" is called):

Castle.Core.Internal.LateBoundComponent is not a
GenericTypeDefinition. MakeGenericType may only be called on a type
for which Type.IsGenericTypeDefinition is true.


Full stack trace:
[InvalidOperationException: Castle.Core.Internal.LateBoundComponent is
not a GenericTypeDefinition. MakeGenericType may only be called on a
type for which Type.IsGenericTypeDefinition is true.]
System.RuntimeType.MakeGenericType(Type[] instantiation) +9484789

Castle.MicroKernel.Handlers.DefaultGenericHandler.ResolveCore(CreationContext
context, Boolean requiresDecommission, Boolean instanceRequired) in e:
\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\Handlers
\DefaultGenericHandler.cs:52
Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext
context, Boolean instanceRequired) in e:\OSS.Code\Castle.Windsor\src
\Castle.Windsor\MicroKernel\Handlers\AbstractHandler.cs:771
Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext
context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\Handlers\AbstractHandler.cs:369

Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveServiceDependency(CreationContext
context, ComponentModel model, DependencyModel dependency) in e:
\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\Resolvers
\DefaultDependencyResolver.cs:390

Castle.MicroKernel.Resolvers.DefaultDependencyResolver.Resolve(CreationContext
context, ISubDependencyResolver contextHandlerResolver, ComponentModel
model, DependencyModel dependency) in e:\OSS.Code\Castle.Windsor\src
\Castle.Windsor\MicroKernel\Resolvers\DefaultDependencyResolver.cs:243

Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateConstructorArgumentsCore(ConstructorCandidate
constructor, Object[] arguments, CreationContext context, Type[]
signature) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\ComponentActivator\DefaultComponentActivator.cs:353

Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateConstructorArguments(ConstructorCandidate
constructor, CreationContext context, Type[]& signature) in e:\OSS.Code
\Castle.Windsor\src\Castle.Windsor\MicroKernel\ComponentActivator
\DefaultComponentActivator.cs:338

Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext
context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\ComponentActivator\DefaultComponentActivator.cs:90

Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext
context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\ComponentActivator\DefaultComponentActivator.cs:70

Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext
context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\ComponentActivator\AbstractComponentActivator.cs:75

Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext
context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\Lifestyle\AbstractLifestyleManager.cs:42

Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleManager.Resolve(CreationContext
context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\Lifestyle\PerWebRequestLifestyleManager.cs:55

Nancy.BootStrappers.Windsor.HybridPerWebRequestLifestyleManager`1.Resolve(CreationContext
context) +125

Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext
context, Boolean requiresDecommission, Boolean instanceRequired) in e:
\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\Handlers
\DefaultHandler.cs:61
Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext
context, Boolean instanceRequired) in e:\OSS.Code\Castle.Windsor\src
\Castle.Windsor\MicroKernel\Handlers\AbstractHandler.cs:771

Castle.MicroKernel.Handlers.AbstractHandler.TryResolve(CreationContext
context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\Handlers\AbstractHandler.cs:376
Castle.MicroKernel.DefaultKernel.TryResolveComponent(IHandler
handler, Type service, IDictionary additionalArguments) in e:\OSS.Code
\Castle.Windsor\src\Castle.Windsor\MicroKernel\DefaultKernel.cs:915
Castle.MicroKernel.DefaultKernel.ResolveAll(Type service,
IDictionary arguments) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor
\MicroKernel\DefaultKernel_Resolve.cs:277
Castle.MicroKernel.DefaultKernel.ResolveAll(Type service) in e:
\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel
\DefaultKernel_Resolve.cs:250
Castle.Windsor.WindsorContainer.ResolveAll(Type service) in e:
\OSS.Code\Castle.Windsor\src\Castle.Windsor\Windsor
\WindsorContainer.cs:896
Castle.Windsor.WindsorContainer.ResolveAll() in e:\OSS.Code
\Castle.Windsor\src\Castle.Windsor\Windsor\WindsorContainer.cs:891

Nancy.Bootstrappers.Windsor.WindsorNancyAspNetBootstrapper.GetAllModules(IWindsorContainer
container) +63

Nancy.Bootstrapper.NancyBootstrapperWithRequestContainerBase`1.GetAllModules(NancyContext
context) +78
Nancy.Routing.RouteCache..ctor(INancyModuleCatalog moduleCatalog,
IModuleKeyGenerator moduleKeyGenerator, INancyContextFactory
contextFactory) +112



On May 17, 1:07 am, Krzysztof Koźmic <krzysztof.koz...@gmail.com>
wrote:
> .UsingFactoryMethod((k,m,c) => YourFactory(m.Implementation));
>
> On 17/05/2012 5:35 PM, Nik Pinski wrote:
>
>
>
>
>
>
>
> > Could you be a little more clear?  This really isn't much to go on,
> > and while I understand conceptually the kind of reflection the factory
> > method would have to do, I don't understand how to register the
> > generic MyGenericObject<T> where T is passed in to the factory method...
>
> > On Tue, May 15, 2012 at 2:59 AM, Krzysztof Koźmic
> > <krzysztof.koz...@gmail.com <mailto:krzysztof.koz...@gmail.com>> wrote:
>
> >     yes
>
> >     On 15/05/2012 8:54 AM, npinski wrote:
>
> >         That's fine.  But i'm not sure I understand...what kind of
> >         signature
> >         would the configuration have to have?  I assume you are
> >         implying the
> >         type of the generic parameter would need to be passed in to the
> >         factory method?
>
> >         On May 11, 3:45 pm, Krzysztof
> >         Koźmic<krzysztof.koz...@gmail.com
> >         <mailto:krzysztof.koz...@gmail.com>>
> >     <mailto:castle-pro...@googlegroups.com>.
> >     To unsubscribe from this group, send email to
> >     castle-project-d...@googlegroups.com
> >     <mailto:castle-project-devel%2Bunsu...@googlegroups.com>.

Krzysztof Koźmic

unread,
Jun 26, 2012, 4:23:20 PM6/26/12
to castle-pro...@googlegroups.com
Right, my bad.

The CreationContext.RequestedType will give you what you need.

@K
Reply all
Reply to author
Forward
0 new messages