自定義 LifeStyle - IScopeAccessor

通過實現自定義 IScopeAccessor,你可以建立不同型別的範圍。對於以下示例,我有兩個類 FooBar,其中 Bar 將使用自定義 LifeStyle 註冊。

每個人都有一個 ID 來協助測試

public class Foo
{
    public Guid FooId { get; } = Guid.NewGuid();
}

public class Bar
{
    public Guid BarId { get; } = Guid.NewGuid();
}

要將 Bar 註冊為 LifestyleScoped<T>,我實施了 FooScopeAccessor

public class FooScopeAccessor : IScopeAccessor
{
    private static readonly ConcurrentDictionary<Foo, ILifetimeScope> collection = new ConcurrentDictionary<Foo, ILifetimeScope>();

    public ILifetimeScope GetScope(CreationContext context)
    {
        return collection.GetOrAdd(context.AdditionalArguments["scope"] as Foo, new DefaultLifetimeScope());
    }

    public void Dispose()
    {
        foreach (var scope in collection)
        {
            scope.Value.Dispose();
        }
        collection.Clear();
    }
}

註冊和解決:

WindsorContainer container = new WindsorContainer();
container.Register(Component.For<Foo>().LifestyleTransient());

var foo1 = container.Resolve<Foo>(); // FooId = 004350ac-40ff-4d1a-8022-7977f94eb418
var foo2 = container.Resolve<Foo>(); // FooId = 714aad8a-e4a2-4950-9017-e387c1c56133

container.Register(Component.For<Bar>().LifestyleScoped<FooScopeAccessor>());

var bar1 = container.Resolve<Bar>(new Dictionary<string, Foo> { ["scope"] = foo1 });     
//                                              c144ba90-ce37-45c2-89d4-593d127fb723

var bar2 = container.Resolve<Bar>(new Dictionary<string, Foo> { ["scope"] = foo1 });
//                                              c144ba90-ce37-45c2-89d4-593d127fb723

var bar3 = container.Resolve<Bar>(new Dictionary<string, Foo> { ["scope"] = foo2 }); 
//                                              bcfe7ba4-cfb3-4b6e-8ecc-a3a3e5055bea

var bar4 = container.Resolve<Bar>(new Dictionary<string, Foo> { ["scope"] = foo1 }); 
//                                              c144ba90-ce37-45c2-89d4-593d127fb723

如上所述,使用 Foo1 解析的 bar2bar3 都是對同一個物件的引用,而 bar4 已經用 Bar 的新例項解析了

有關實現自定義 IScopeAccessor 的更多詳細資訊,請參閱 Castle 的文件