我有Player
和CharacterSpawner
,其构造函数中包含IPlayer
。
class CharacterSpawner : ICharacterSpawner
{
public CharacterSpawner(IPlayer player, SomeDep dep)
{
// ...
}
public void SpawnNext()
{
// ...
}
}
在我的应用的某些部分,我想针对特定ICharacterSpawner
解析IPlayer
。我想缓存ICharacterSpawner
个实例,以便每个IPlayer
只创建一个实例。我怎么能用Autofac做到这一点?
更新 建议的现有答案不是关于AutoFac,而是关于Castle。我需要在项目中使用Autofac。
答案 0 :(得分:1)
Autofac中没有内置支持可以满足您的需求,但我可以通过注册lambda表达式来查看解决方案,该表达式将从ICharacterSpawner
中选择Dictionary
。关键是将提供的上下文转换为IInstanceLookup
以检索提供的IPlayer
以下是适用于您的案例的示例代码。我使用IService
和IOwner
定义为:
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));