Closed xp-development closed 6 years ago
Hi @jan-schubert
I don't have any specific documentation on creating your own lifestyle, that said you should be able to do what you are looking to do pretty easy by looking at SingletonPerScopeLifestyle. You can remove the thread safe bool as you don't need it for your use case. Just replace the GetValueFromScope method.
This is my implementation.
public static T GetValueFromScope<T>(IExportLocatorScope scope, ActivationStrategyDelegate creationDelegate, string uniqueId)
{
var id = Task.CurrentId.HasValue ? $"{uniqueId}ta{Task.CurrentId.Value}" : $"{uniqueId}th{Thread.CurrentThread.ManagedThreadId}";
return (T)(scope.GetExtraData(id) ?? scope.SetExtraData(id, creationDelegate(scope, scope, null), false));
}
It works fine, but the Container.ExtraData collection is getting bigger and bigger. Is it possible to remove extra data from container, if a task was finished?
[Fact]
public void TaskOrThreadLifestyle()
{
var container = new DependencyInjectionContainer();
container.Configure(c => c.Export<BasicService>().As<IBasicService>().Lifestyle.Custom(new TaskOrThreadLifestyle(false)));
IBasicService instance = null;
IBasicService instance2 = null;
Task.Run(() =>
{
instance = container.Locate<IBasicService>();
// ------> expected container.ExtraData.Count == 1
}).Wait();
// ------> expected container.ExtraData.Count == 0, but was 1
Task.Run(() =>
{
instance2 = container.Locate<IBasicService>();
}).Wait();
Assert.NotNull(instance);
Assert.NotNull(instance2);
Assert.NotSame(instance, instance2);
}
@jan-schubert there isn't a way currently but maybe what you could do is instead of putting it in the extra data directly you put a ConcurrentDictionary in the extra data that you can add and remove easily.
The other option you could do at the moment is set the value to null.
Moving forward it does seem like a worth while feature it might make sense to open a new issue requesting the ability to remove extra data. I don't have a lot of time right at the moment but it could be useful in the future.
@jan-schubert can I close this out or do you have more questions?
All fine! Thanks.
Hi @ipjohnson,
I hope that the following question is my last. :)
I think I need custom lifestyle or is there another method out of the box. I want to receive one service per task or if there is no task one service per thread as fallback.
Is there some documentation how to develop an own lifestyle?
In Ninject I develop an own scope resolver: