Windsor MixIn is a Singleton?

2019-03-06 07:27发布

问题:

I have a MixIn that requires some state to operate.

I am registering it as so..

    container.Register(Component.For(Of ICat) _
                        .ImplementedBy(Of Cat) _
                        .LifeStyle.Transient _
                        .Proxy.MixIns(New MyMixin()))

When I call container.Resolve(of ICat), I get back a proxy for ICat, which also implements IMixin.

However, if I call container.Resolve(of ICat) again, I get a new proxy for ICat, but MyMixin is the SAME instance. (Which makes sense because I didn't tell the container any way to create IMixin)

So, IMixin is a Singleton, even though the Component's lifestyle is Transient.

How can I tell Windsor, though the Fluent Interface, to create a new Instance of MyMixIn for the component?

回答1:

I think I resolved this.

Instead of using Proxy.Mixins, I created a custom Activator()

Public Class MixInActivator(Of T)
   Inherits Castle.MicroKernel.ComponentActivator.DefaultComponentActivator

  Public Sub New(ByVal model As Castle.Core.ComponentModel, ByVal kernel As Castle.MicroKernel.IKernel, ByVal OnCreation As Castle.MicroKernel.ComponentInstanceDelegate, ByVal OnDestruction As Castle.MicroKernel.ComponentInstanceDelegate)
    MyBase.New(model, kernel, OnCreation, OnDestruction)
  End Sub

  Protected Overrides Function InternalCreate(ByVal context As Castle.MicroKernel.CreationContext) As Object

    Dim obj As Object = MyBase.InternalCreate(context)
    If GetType(T).IsAssignableFrom(obj.GetType) = False Then
        Dim options As New Castle.DynamicProxy.ProxyGenerationOptions
        Dim gen As New Castle.DynamicProxy.ProxyGenerator
        options.AddMixinInstance(Kernel.Resolve(Of T))
        obj = gen.CreateInterfaceProxyWithTarget(Model.Service, obj, options)
    End If
    Return obj
 End Function
End Class

So now, the component is registered like this

 container.Register(Component.For(Of ICat) _
                     .ImplementedBy(Of Cat) _
                     .LifeStyle.Is(Castle.Core.LifestyleType.Transient) _
                     .Activator(Of MixInActivator(Of IMixin)))

And IMixin is registered as follows

container.Register(Component.For(Of IMixin) _
                       .ImplementedBy(Of MyMixin) _
                       .LifeStyle.Is(Castle.Core.LifestyleType.Transient) _
                       .Named("MyMixin"))


回答2:

I'm not sure how it bubbles up to Windsor, but at DynamicProxy level, there's mixin Instance per proxy type. So if you're creating yourself mixin instances, you may be also each time be generating a new proxy type. To circumvent this, override Equals and GetHashCode in your mixed in type.

I may however not be right, so you may want to make sure first.