TL;DR: Does Autofac support something like AutoFixture's fixture.Get()
mechanism ?
I'm using Autofac and need to invoke async factory methods which look like this:
class AppModel
{
public static async Task<AppModel> CreateAsync(IDependency x, IDependency2 y)
{ ... }
}
What is the simplest way for me to execute such a method and have the arguments be supplied by Autofac? i.e., I want to be able to do something like:
Task<AppModel> creationTask = <some autofaccery>(AppModel.CreateAsync);
var appModel = await creationTask();
where <some autofaccery>
represents some mechanism of interacting with ContainerBuilder
and/or IContainer
and/or some form of generated Delegates or similar which is succinct in nature and isolates me from specifying the arguments to the Factory Method explicitly. i.e., I want to avoid having to explicitly resolve each argument [and/or have to update them as the dependencies change] like I do atm:
var appModel = await AppModel.CreateAsync(
container.Resolve<IDependency>(),
container.Resolve<IDependency2>());
I am in infrastructure components territory, close to the Composition Root and could potentially programmatically define Component Registrations and/or do other nastiness that should be confined to there. I don't mind reflection being involved as it's only being invoked once.
What is critical is that I do need any Exception
s emanating from the Task
to be observed.
The Task<T>
is a red herring to a large degree, but the point is that following the normal pattern of defining a synchronous factory method and having Autofac work through that won't fly (at least not directly), i.e. I can't just change it to:
public static AppModel CreateAsync(IDependency x, IDependency2 y)
{ ... }
I'd also like to avoid two-phase initialization - I don't need the object to be available until it's been initialized.
In addition to necessitating a set of ugly extension methods, my first answer leaks the signature of the factory into the calling modules, necessitating references to namespaces that are not directly required. In order to hide this, one can use the same scheme, but encapsulate the dependency set in an
AsyncFactory
class :-Then the caller can use a uniform mechanism to use the factory:-
(Note there is no restatement of the argument types so adding further dependencies to the
AsyncFactory
will not trigger knock-on changes to the calling code)Abusing
LazyTask<T>
, one can transform aCreateAsync
method into something Autofac can resolve :- a Type [derived fromLazyTask<T>
], which looks like so:This can be consumed as follows:-
Not accepting this as I still feel there is an opportunity for this to be clearer - i.e. if Autofac was to apply a special treatment to
Task<T> CreateAsync
methods written as follows:-automatically registering them as the type
Task<T>
, allowing one to consume as follows without relying on myTask
wrapper type:-(Inspired by the TL;DR I added at the top)
You could implement a
ResolveAsync
family of methods:-This allows me to do:
Or obviously these could be turned into extension methods:-
working on a wrapper to allow C#'s primitive type inference to be used :(I'm going to conserve my energy and not sink any further time into achieving a proper solution in a language/async paradigm not built for the job.