2013-07-11 49 views
2

我使用温莎城堡作为IoC容器,我想解决这依赖于另外一个对象:取决于构造温莎城堡的生活方式参数

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

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

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

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

你知道如何做到这一点吗?

+0

什么是你的确切使用情况,我的依赖?你为什么需要这个? – Steven

+0

其实IService是一个工厂,MyObject是工厂依赖的一个对象(可能是一个WCF接收对象)。 – enenkey

+3

防止为构造函数注入运行时依赖项(因为'obj'似乎是)。将值传入“Resolve”方法是一种设计气味。如果'IService'是一个工厂,将'obj'传入工厂'CreateXXX'方法,因为它显然是工厂合同的一部分。 – Steven

回答

3

我不知道内置解决方案,但您始终可以创建自己的ILifestyleManager
仅供参考,你可以看看implementation of SingletonLifestyleManager

我从来没有真正研究过如何为城堡制作自定义生活方式(我记得我们为Unity做了一个),但通常的想法是决定何时解决一个新的实例(城堡代码中的CreateInstance)和何时使用存储的值。

ConcurrentDictionary可以帮助你的情况下存储(虽然不知道什么城堡的burden做的,你可能想研究这一点)。如果您的objs是动态创建的,请注意泄漏 - 您可能对ConditionalWeakTable感兴趣。

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

+0

这可能对我有帮助,你有没有例子? – enenkey

+0

@enenkey用更多的细节更新了答案。 –

+0

谢谢我将会看到我如何实现自己的ILifestyleManager。 那么,我不同意@Steven在工厂外使用obj(请参阅上面的注释) – enenkey

1

我终于创建了一个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>()