2015-09-28 29 views
0

我有PlayerCharacterSpawner這需要在其構造IPlayerCache實例

class CharacterSpawner : ICharacterSpawner 
    { 
     public CharacterSpawner(IPlayer player, SomeDep dep) 
     { 
      // ... 
     } 

     public void SpawnNext() 
     { 
      // ... 
     } 
    } 

在我的應用程序的某些部分我想解決ICharacterSpawner特定IPlayer。我想緩存ICharacterSpawner實例,以便只有一個每IPlayer被創建。我如何用Autofac做到這一點?

更新 建議現有的答案不是關於AutoFac,而是關於Castle而不是。我需要爲我的項目使用Autofac。

+0

可能重複[如何使AutoFac對每個頂級對象使用嵌套依賴關係的相同實例? (每個集線器SignalR依賴注入)](http://stackoverflow.com/questions/25670739/how-to-make-autofac-use-same-instance-of-nested-dependency-per-top-level-object) – qujck

+0

@qujck的答案不是關於AutoFac,作者決定使用Castle。我需要爲我的項目使用Autofac。 – Vlad

+0

你能描述一下你的場景嗎?有些更好的解決方案可以更好地滿足您的需求 –

回答

1

Autofac中沒有內置的支持,可以滿足您的需求,但我可以通過註冊一個lambda表達式來查看解決方案,該表達式將從Dictionary中選擇ICharacterSpawner。關鍵是將提供的上下文投射到IInstanceLookup以檢索提供的IPlayer

以下是適用於您的案例的示例代碼。我用IServiceIOwner被定義爲:

interface IService 
{ 
    String Code { get; } 
} 
class MyService : IService 
{ 
    public MyService() : this(DateTime.Now.Ticks.ToString()) 
    { } 
    public MyService(String code) 
    { 
     this.Code = code; 
    } 
    public String Code { get; } 
} 

interface IOwner { } 
class Owner : IOwner 
{ 
    public Owner(IService service) 
    { 
     Console.WriteLine($"new owner for service {service.Code}"); 
    } 
} 

而且我註冊的樣子:

ContainerBuilder builder = new ContainerBuilder(); 
var owners = new ConcurrentDictionary<IService, IOwner>(); 
builder.RegisterType<MyService>().As<IService>().OnRelease(o => 
{ 
    IOwner owner; 
    owners.TryRemove(o, out owner); 
}); 
builder.RegisterType<Owner>().Named<IOwner>("newOwner"); 
builder.Register(c => 
{ 
    IEnumerable<Parameter> parameters = Enumerable.Empty<Parameter>(); 
    IInstanceLookup instanceLookup = c as IInstanceLookup; 
    if (instanceLookup != null) 
    { 
     parameters = instanceLookup.Parameters; 
    } 

    IService service = parameters.OfType<TypedParameter>() 
           .Where(tp => tp.Type == typeof(IService)) 
           .Select(tp => tp.Value) 
           .OfType<IService>() 
           .FirstOrDefault(); 
    if (service == null) 
    { 
     service = c.Resolve<IService>(); 
     parameters = parameters.Concat(new Parameter[] { 
      TypedParameter.From<IService>(service) 
     }); 
    } 

    IOwner owner = owners.GetOrAdd(service, _ => 
     c.ResolveNamed<IOwner>("newOwner", parameters) 
    ); 

    return owner; 
}).As<IOwner>(); 

IContainer container = builder.Build(); 

然後,你將能夠做到這一點的

IService service1 = new MyService("service1"); 
IService service2 = new MyService("service2"); 

container.Resolve<IOwner>(TypedParameter.From<IService>(service1)); 
container.Resolve<IOwner>(TypedParameter.From<IService>(service1)); 
container.Resolve<IOwner>(TypedParameter.From<IService>(service2));