using System.Collections.Generic;
using System.Threading.Tasks;
using Castle.Core.Internal;
using Castle.DynamicProxy;
using Castle.MicroKernel;
using Castle.MicroKernel.ComponentActivator;
using Castle.MicroKernel.Context;
using Castle.MicroKernel.Registration;
static void Main(string[] args)
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For<IFoo>()
.UsingFactoryMethodAllowNull(Foo.CreateFoo));
container.Register(Component
.For<IBar>().ImplementedBy<Bar>());
var service = container.Resolve<IBar>();
public static class CRE {
public static ComponentRegistration<TService> UsingFactoryMethodAllowNull<TImpl, TService>(this ComponentRegistration<TService> self, Func<TImpl> factoryMethod,
bool managedExternally = false)
where TImpl : TService where TService : class
return self.UsingFactoryMethodAllowNull((k, m, c) => factoryMethod(), managedExternally);
public static ComponentRegistration<TService> UsingFactoryMethodAllowNull<TImpl, TService>(this ComponentRegistration<TService> self,
Func<IKernel, TImpl> factoryMethod,
bool managedExternally = false)
where TImpl : TService where TService : class
return self.UsingFactoryMethodAllowNull((k, m, c) => factoryMethod(k), managedExternally);
public static ComponentRegistration<TService> UsingFactoryMethodAllowNull<TService,TImpl>(
this ComponentRegistration<TService> self,
Func<IKernel, ComponentModel, CreationContext, TImpl> factoryMethod,
bool managedExternally = false)
where TImpl : TService where TService : class
self.Activator<FactoryMethodActivatorAllowingNull<TImpl>>()
.ExtendedProperties(Property.ForKey("factoryMethodDelegate").Eq(factoryMethod));
self.ExtendedProperties(Property.ForKey("factory.managedExternally").Eq(managedExternally));
List<Type> potentialServices = (List<Type>) self.GetType()
.GetField("potentialServices", BindingFlags.NonPublic | BindingFlags.Instance)
var firstService = potentialServices.First().GetTypeInfo();
if (self.Implementation == null &&
(firstService.IsClass == false || firstService.IsSealed == false))
self.ImplementedBy(typeof(LateBoundComponent));
public class FactoryMethodActivatorAllowingNull<T> : DefaultComponentActivator, IDependencyAwareActivator
protected readonly Func<IKernel, ComponentModel, CreationContext, T> creator;
protected readonly bool managedExternally;
public FactoryMethodActivatorAllowingNull(ComponentModel model, IKernelInternal kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
: base(model, kernel, onCreation, onDestruction)
creator = Model.ExtendedProperties["factoryMethodDelegate"] as Func<IKernel, ComponentModel, CreationContext, T>;
managedExternally = (Model.ExtendedProperties["factory.managedExternally"] as bool?).GetValueOrDefault();
throw new ComponentActivatorException(
GetType().Name +" received misconfigured component model for "+Model.Name+". Are you sure you registered this component with 'UsingFactoryMethod'?", Model);
public bool CanProvideRequiredDependencies(ComponentModel component)
public bool IsManagedExternally(ComponentModel component)
return managedExternally;
protected override void ApplyCommissionConcerns(object instance)
if (managedExternally || instance == null)
base.ApplyCommissionConcerns(instance);
protected override void ApplyDecommissionConcerns(object instance)
if (managedExternally || instance==null)
base.ApplyDecommissionConcerns(instance);
public override object Create(CreationContext context, Burden burden)
var instance = InternalCreate(context);
burden.SetRootInstance(instance);
if (OnCreation != null) OnCreation.Invoke(Model, instance);
protected override object Instantiate(CreationContext context)
object instance = creator(Kernel, Model, context);
if (ShouldCreateProxy(instance))
instance = Kernel.ProxyFactory.Create(Kernel, instance, Model, context);
protected override void SetUpProperties(object instance, CreationContext context)
private bool ShouldCreateProxy(object instance)
if (Kernel.ProxyFactory.ShouldCreateProxy(Model) == false)
return ProxyUtil.IsProxy(instance) == false;
public static IFoo CreateFoo()
private readonly IFoo foo;
public Bar(IFoo foo = null)
Console.WriteLine("My foo was "+foo == null ? "NULL" : foo.ToString());