2

我使用 Castle Windsor 作为 IoC 容器,我想根据另一个对象来解析一个对象:

public MyService : IService
{
  public MyService(MyObject obj)
  {
  }
}

在哪里解决:

var service1 = container.Resolve<IService>( new { obj = obj1 });
var service2 = container.Resolve<IService>( new { obj = obj1 });

var service3 = container.Resolve<IService>( new { obj = obj2 });

我希望 service1 与 service2 相同(相同的参考),而 service3 不同。所以我需要一种不同于 Singleton 或 Transient 的生活方式。只要 obj 参数相同(通过引用),就应该返回相同的对象。

你知道如何实现吗?

4

2 回答 2

3

我不知道内置解决方案,但您始终可以创建自己的ILifestyleManager.
作为参考,您可以查看SingletonLifestyleManager 的实现

我从未真正研究过如何为 Castle 制作自定义生活方式(据我记忆,我们为 Unity 做过一个),但通常的想法是决定何时解析一个新实例(CreateInstance在 Castle 代码中)以及何时使用存储的价值。

ConcurrentDictionary可以帮助您进行存储(尽管不知道 Castle 的burden作用,但您可能需要对此进行研究)。如果您是动态创建的,请注意泄漏objs——您可能对ConditionalWeakTable.

注意:我同意@Steven 的观点,在你的情况下obj通常应该是一个参数Create方法,但为了完整起见,我也会保留一个直接的答案。

于 2013-07-11T11:45:49.067 回答
2

我终于创建了一个 IScopeAccessor,如:

public class PerConstructorScopeAccessor : IScopeAccessor
{
    private static IDictionary<int, ILifetimeScope> Cache = new ConcurrentDictionary<int, ILifetimeScope>();

    public ILifetimeScope GetScope(Castle.MicroKernel.Context.CreationContext context)
    {
        int key = GetContextKey(context);
        if (!Cache.ContainsKey(key))
            Cache.Add(key, new DefaultLifetimeScope());

        return Cache[key];
    }

    private int GetContextKey(Castle.MicroKernel.Context.CreationContext context)
    {
        int hash = 0;

        foreach (var value in context.AdditionalArguments.Values)
        {
            hash = HashCode.CombineHashCode(hash, value.GetHashCode());
        }

        return hash;
    }

    #region IDisposable

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

而不是我使用注册我的依赖项LifestyleScoped<PerConstructorScopeAccessor>()

于 2013-07-11T13:19:26.443 回答