I have a wrapper class as below:
// this is not used for IoC purposes, but by code to cast object to known T
internal interface ITaskCompletionSourceWrapper
{
void SetResult(object result);
/* snip */
}
internal class TaskCompletionSourceGenericWrapper<TResult> : ITaskCompletionSourceWrapper
{
readonly TaskCompletionSource<TResult> tcs;
public TaskCompletionSourceGenericWrapper() =>
this.tcs = new TaskCompletionSource<TResult>(TaskCreationOptions.RunContinuationsAsynchronously);
public void SetResult(object result) => tcs.SetResult((TResult)result);
/* snip */
}
Where i currently instantiate using Activator:
var responseType = request
.GetType()
.GetInterfaces()
.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>))
GetGenericArguments()[0];
var wrapperType = typeof(TaskCompletionSourceGenericWrapper<>).MakeGenericType(responseType);
var tcsWrapper = this.container.GetInstance(wrapperType) as ITaskCompletionSourceWrapper;
I switched this to SimpleInjector (as may use logging and other IOC goodness) and thought all was well until I found an issue (which was due to lifestyle being shared):
/* snip responseType code from above */
var wrapperType = typeof(TaskCompletionSourceGenericWrapper<>).MakeGenericType(responseType);
var tcsWrapper = this.container.GetInstance(wrapperType) as ITaskCompletionSourceWrapper;
// i can see the type has been registered as scoped, but we need it to be unique
[30] = ServiceType = TaskCompletionSourceGenericWrapper<Object>, Lifestyle = Async Scoped
The above is being called within a AsyncScopedLifestyle.BeginScope block.
I would like to instantiate this wrapper at runtime using SimpleInjector (but ensuring Lifestyle.Transient):
The types for the wrapper are pretty much arbitrary from int, string, bool etc but could also be simple POCO classes.
This is similar to a case of open generic registration but I would rather avoid having other developers specify assemblies for the simple types (as for sure they will forget, and their classes are simple anyways - command/query POCOs and the like).
How can I achieve the above please or am I forced to register collection?
Or is this deeper with lifestyle mismatches - I hope not, since the wrapper has no dependencies (and will not other than ILogger perhaps) is only doing something instantiation of a simple class (which I want to replace Activator rather than decouple components IoC style).