为什么Castle Windsor的Typeton Factory注册为Singleton生活方式?

时间:2014-05-17 00:38:49

标签: castle-windsor windsor-facilities

我对Castle Windsor的情况非常奇怪,工厂注册为LifeStyle.Singleton的地方似乎处于某个位置。几个小时后,我能够简化生产案例到这个摘录:

修改 经过一些调查后,我将问题简化为几乎无关紧要的案例(原始版本保存在下面):

public interface IFactory {
    IAnotherFactory CreateAnother();
}

public interface IAnotherFactory {
    A CreateA();
}

public class A {}

[Test]
public void IsItABug() {
    Container.Kernel.AddFacility<TypedFactoryFacility>();
    Container.Register(Component.For<A>().LifestyleTransient(),
                       Component.For<IFactory>().AsFactory().LifestyleTransient(),
                       Component.For<IAnotherFactory>().AsFactory().LifestyleSingleton());

    // uncomment this line to make test pass
    // var makeAnotherUsedInMainContainerScopeBeforeFactoryCreation =
    //     Сontainer.Resolve<IAnotherFactory>();

    var factory = Container.Resolve<IFactory>();
    factory.CreateAnother();
    Container.Release(factory);
    var another = Container.Resolve<IAnotherFactory>();
    another.CreateA(); // throws ObjectDisposedException
}

Ant异常现在要短得多:

System.ObjectDisposedException : The factory was disposed and can no longer be used.
Object name: 'this'.
   at Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Intercept(IInvocation invocation) in TypedFactoryInterceptor.cs: line 59
   at Castle.DynamicProxy.AbstractInvocation.Proceed() in d:\work\16de7b8c88ab14af\src\Castle.Core\DynamicProxy\AbstractInvocation.cs: line 145
   at Castle.Proxies.IAnotherFactoryProxy.CreateA()
   at Castle.Windsor.Tests.Facilities.TypedFactory.Components.TypedFactoryAndSubContainersTestCase.IsItABug() in TypedFactoryAndSubContainersTestCase.cs: line 102

我相信现在这不再是一个问题了,因为Windsor过去有过非常相似的问题(IOC-345),所以我写了失败的测试和submitted an issue

原始版本

public interface IFactory {
    Y CreateY();
    Z CreateZ();
    void Release(Y obj);
}

public class X {
    public X(IFactory factory) {
        var y = factory.CreateY();
        factory.Release(y);
        factory.CreateY();
    }
}

public class Y {
    public Y(IFactory factory) {
        factory.CreateZ();
    }
}

public class Z {
    public Z(IAnotherFactory anotherFactory) {
        anotherFactory.CreateA(); // <--- on second time anotherFactory is disposed already O_o
    }
}

public interface IAnotherFactory {
    A CreateA();
}

public class A {}

[TestFixture]
public class Class1
{
    [Test]
    public void IsItABug()
    {
        var c = new WindsorContainer();
        c.Kernel.AddFacility<TypedFactoryFacility>();
        c.Register(Component.For<X>().LifestyleTransient(),
                   Component.For<Y>().LifestyleTransient(),
                   Component.For<Z>().LifestyleTransient(),
                   Component.For<A>().LifestyleTransient(),
                   Component.For<IFactory>().AsFactory().LifestyleTransient(),
                   Component.For<IAnotherFactory>().AsFactory().LifestyleSingleton());

        c.Resolve<X>();
    }
}

在Windsor 3.2上面的标记行上,我得到了例外:

Castle.MicroKernel.ComponentActivator.ComponentActivatorException : ComponentActivator: could not instantiate Sandbox.GM.Config.X
  ----> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> Castle.MicroKernel.ComponentActivator.ComponentActivatorException : ComponentActivator: could not instantiate Sandbox.GM.Config.Y
  ----> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> Castle.MicroKernel.ComponentActivator.ComponentActivatorException : ComponentActivator: could not instantiate Sandbox.GM.Config.Z
  ----> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> System.ObjectDisposedException : The factory was disposed and can no longer be used.
Object name: 'this'.

   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy)
   at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, ref Burden burden)
   at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
   at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
   at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments)
   at Castle.Windsor.WindsorContainer.Resolve()
   at TestApp.Class1.IsItABug() in Class1.cs: line 56
--TargetInvocationException
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeConstructorInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.FastCreateInstance(Type implType, Object[] arguments, ConstructorCandidate constructor)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
--ComponentActivatorException
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy)
   at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, ref Burden burden)
   at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
   at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
   at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
   at Castle.Facilities.TypedFactory.TypedFactoryComponentResolver.Resolve(IKernelInternal kernel, IReleasePolicy scope)
   at Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Resolve(IInvocation invocation)
   at Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IFactoryProxy.CreateY()
   at TestApp.X..ctor(IFactory factory) in Class1.cs: line 19
--TargetInvocationException
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeConstructorInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.FastCreateInstance(Type implType, Object[] arguments, ConstructorCandidate constructor)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
--ComponentActivatorException
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy)
   at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, ref Burden burden)
   at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
   at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
   at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
   at Castle.Facilities.TypedFactory.TypedFactoryComponentResolver.Resolve(IKernelInternal kernel, IReleasePolicy scope)
   at Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Resolve(IInvocation invocation)
   at Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IFactoryProxy.CreateZ()
   at TestApp.Y..ctor(IFactory factory) in Class1.cs: line 25
--TargetInvocationException
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeConstructorInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.FastCreateInstance(Type implType, Object[] arguments, ConstructorCandidate constructor)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
--ObjectDisposedException
   at Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IAnotherFactoryProxy.CreateA()
   at TestApp.Z..ctor(IAnotherFactory anotherFactory) in Class1.cs: line 31

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我坚信现在这是一个错误,因此问题是:https://github.com/castleproject/Windsor/pull/61