I am using WebAPI with Autofac and starting a long running task (fire and forget stuff) which will be alive after the lifetime of HTTP request. Therefore, I would like to prevent the ApiController to automatically dispose the object which consists the long running task, after ApiController lifetime ends.
In the Web API controller I would like to use Owned<T> class in order to inject one of the dependencies without binding it to the LifeTimeScope of the ApiController instance. It seems Owned<T> is a good choice for that, but I would like inherit from it in order to have virtual (polymorphic) Value property which I can mock with the Moq library.
However, when I inherit from Owned<T> autofac does not recognize (due to the reflection?) my MyOwned<T> and throws the exception below.
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'autofak.Meta' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Func'2[System.Int32,autofak.MyOwned'1[autofak.Root]] root' of constructor 'Void .ctor(System.Func'2[System.Int32,autofak.MyOwned'1[autofak.Root]])'.
This is my top-level class which depends on Root class.
class Meta
{
public MyOwned<Root> Root { get; private set; }
public Meta(Func<int, MyOwned<Root>> root)
{
Root = root(2);
}
}
My registration code is below:
var container = new ContainerBuilder();
container.RegisterType<child>();
container.RegisterType<grandchild>();
container.RegisterType<Root>();
container.RegisterType<Meta>();
var builder = container.Build();
Is it possible to inherit from Owned and make it work or should I try a different approach?
Update:
Besides the accepted solution, I also followed a different path by creating a SingleInstance() factory in order to create new LifeTimeScope objects from the root/application lifetimescope. Similar to Owned<T> class I created a new class which also stores this new lifetime (created from root lifetime scope) for each task and makes it possible to call Dispose() as in the Owned<T>.
The easiest way to do what you want would be to create a new component that uses a Owned<T> instead of inheriting from Owned<T>
public interface IOwned<T> : IDisposable
{
T Value { get; }
}
public class MyOwned<T> : IOwned<T>
{
public MyOwned(Owned<T> owned)
{
this._owned = owned;
}
private readonly Owned<T> _owned;
public virtual T Value
{
get
{
return this._owned.Value;
}
}
public void Dispose()
{
this._owned.Dispose();
}
}
Then register your component using the RegisterGeneric method and ExternallyOwned.
builder.RegisterGeneric(typeof(MyOwned<>))
.As(typeof(IOwned<>))
.ExternallyOwned();
You need to declare it as ExternallyOwned because without this Autofac will try to dispose this component at the end of its ILifetimeScope and the goal of Owned<T> is to let you decide when you dispose the component.
Another option would be to create your own Owned<T> component which is a lot more complex because you will need to implement IRegistrationSource to manage the child ILifetimeScope created by the Owned<T> component.
Related
I have a controller's constructor in which I want to instantiate an object that gets access to the repository via dependency injection.
like this:
ContactController.cs: I get an error because I don't pass an IContactRepository
private ContactOperationsFacade contactOperator;
ContactController(){
contactOperator = new ContactOperationsFacade(//I want to use DI here);
}
ContactOperationsFacade.cs:
private readonly IContactRepository contactRepository;
public ContactOperationsFacade(IContactRepository contactRepositor){
this.contactRepository = contactRepository;
}
How can I instantiate this ContactOperationsFacade object in the controller's constructor still using DI for the repository?
In asp.net core you can do DI chaining as long as scopes allow it. So if A depends on B and the controller wants A you just add both A and B to the di container (ConfigureServices part of your code) and the container will figure it out.
Read more here https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1
ContactController should follow The Explicit Dependencies Principle
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
Also classes should depend on abstractions and not coupled to concretions.
So assuming something like
public class ContactOperationsFacade: IContactOperationsFacade { //<-Note interface/contract
private readonly IContactRepository contactRepository;
public ContactOperationsFacade(IContactRepository contactRepositor){
this.contactRepository = contactRepository;
}
//...
}
The controller should depend on the abstraction that the facade is derived from
public class ContactController: Controller {
private readonly IContactOperationsFacade contactOperator;
public ContactController(IContactOperationsFacade contactOperator){
this.contactOperator = contactOperator;
}
//...
}
And assumes that all the interfaces and implementations are registered with the DI container.
services.AddScoped<IContactOperationsFacade, ContactOperationsFacade>();
once all dependencies are registered the service provider should resolve them when activating the controller.
I am experiencing an issue where DbContext instance injected into a controller is different than the instance injected into a service.
Below is my DbContext registration:
services.AddDbContext<CRMContext>();
services.AddScoped<IEstimateRepository, EstimateRepository>();
services.AddScoped<IMaterialRecordRepository, MaterialRecordRepository>();
My understanding is that by default, AddDbContext adds the context as Scoped, so I would expect that the controller and service would share the same instance.
For reference, here is the controller constructor and the service:
public LineItemController(IEstimateRepository repository)
{
_estimateRepository = repository;
}
public VentChuteLineItemRequiredEventHandler(IEstimateRepository estimateRepository, IMaterialRecordRepository materialRepository)
{
_materialRepository = materialRepository;
_estimateRepository = estimateRepository;
}
I am also using Autofac in this application, however as far as I can tell it is not in any way related to the problem at hand. It seems to be just a fundamental misunderstanding on my part of how the scoped lifetime of the DbContext is handled.
The issue ended up being related to a static class that I was using to create an instance of the service in question.
public static class DomainEventHandler
{
public static ILifetimeScope _container { get; set; }
public static void Raise<T>(T args) where T : IDomainEvent
{
foreach (var handler in _container.Resolve<IEnumerable<IHandle<T>>>())
{
handler.Handle(args);
}
}
}
Since the DomainEventHandler class is static, I assume the .net core dependency resolver knew that the lifetime of any instances it contains to not match the request, and therefore created a new DbContext instance for it to use.
Refactoring this class to no longer be static resolves the issue.
I would like to implement an application-wide container and a (nested) one for each project created by the user. I looked into Owned<T>, but then - as far as I could figure it out - my internal collection of projects would have to be <Owned<Project>> which I do not want and also I failed to inject a project dependency into objects used within the project scope ("circular component dependency"). I considered using a new ContainerBuilder within the project factory, but then the "nested" aspect is missing.
A few exapmles of classes (with the dependencies) I would like to have:
In a global scope: ProjectManager(IProjectFactory)
In each project's scope: Project(IDocumentFactory documentFactory), Document(IProject project, IProjectSettings settings).
So for the project's scope I would register IDocumentFactory, IProjectSettings (and the project itself?).
When a project is closed/disposed all created dependencies should, of course, also be disposed.
If possible, the concrete classes (except for the ProjectFactory) should be Autofac-agnostic.
FYI: The application is a desktop application using C# and Autofac 4.8.
Thanks!
UPDATE: Thanks for your comments, the discussion helped me find my own opinion. Currently I'm settling for something like this in my ProjectFactory:
public Project Create()
{
var scope = _globalScope.BeginLifetimeScope(MyIocHelper.RegisterProjectDependencies);
var p = scope.Resolve<Project>();
_projectScopes.Add(p, scope);
p.Disposing += project_Disposing;
return p;
}
Things to note:
As far as I can tell, using a tag for the lifetime scope is not necessary.
Project raises a Disposing event when its Dispose method is called the first time.
The factory keeps a Dictionary<Project, ILifetimeScope> and cleans it up when the project is disposed.
You can accomplish what you are looking for with a combination of named lifetime scopes and instance-per-lifetime-scope registrations.
Documentation here: http://autofac.readthedocs.io/en/latest/lifetime/working-with-scopes.html#tagging-a-lifetime-scope
You need to:
register your ProjectManager as SingleInstance
register Project as this:
builder.Register<Project>()
.As<IProject>()
.InstancePerMatchingLifetimeScope("project");
This will guarantee that a Project can be resolved (e.g. by a Document) once per each scope tagged as "project".
Implement an OpenProject (or something along) method in ProjectManager. This method should instantiate a LifetimeScope tagged as "project", register in it the IDocumentFactory, IProjectSettings, so they are resolved only once for each project scope, and attach the scope itself onto the Project instance. This is crucial: you need the scope to be disposed when you dispose the project.
public class ProjectManager : IProjectFactory
{
private readonly ILifetimeScope _scope;
public ProjectManager(ILifetimeScope scope)
{
// this is going to be the global scope.
_scope = scope;
}
public Project OpenProject(IDocumentFactory docFactory, IProjectSettings settings)
{
var projectScope = _scope.BeginLifetimeScope("project");
projectScope.RegisterInstance(docFactory).AsImplementedInterfaces();
projectScope.RegisterInstance(settings).AsImplementedInterfaces();
return projectScope.Resolve<Project>();
}
}
public class ProjectScope : IDisposable
{
private readonly ILifetimeScope _scope;
public ProjectManager(ILifetimeScope scope)
{
// this is going to be the project scope.
_scope = scope;
}
public void Dispose() {
if (_scope != null) {
_scope.Dispose();
_scope = null;
}
}
}
public class Project : IDisposable
{
private readonly ProjectScope _scope;
public Project(ProjectScope scope /*, ...*/)
{
_scope = scope;
}
public void Dispose() {
// pay attention that this method will be called 2 times, once by you
// and another time by the underlying LifetimeScope. So this code should
// handle that gracefully (so the _scope == null).
if (_scope != null) {
_scope.Dispose();
_scope = null;
}
}
}
Given all this, you keep every using Autofac out of every class, with the 2 exceptions of the global manager and the ProjectScope. You can change some bits on how the scope is handled, if you accept a single using Autofac in the Project class itself: you can get directly the ILifetimeScope and dispose of it directly.
Hope this helps!
Attempting to inject data into a FluentValidation validator:
public class MyFormValidator : AbstractValidator<MyForm>
{
private readonly IQueryable<Models.User> _users;
public MyFormValidator(IQueryable<Models.User> users)
{
_users = users;
...
}
}
My validator factory:
public class DependencyResolverValidatorFactory : ValidatorFactoryBase
{
private readonly IContainer container;
public DependencyResolverValidatorFactory(IContainer container)
{
this.container = container;
}
public override IValidator CreateInstance(Type validatorType)
{
return container.ResolveOptionalKeyed<IValidator>(validatorType);
}
}
My Autofac configurator:
public class AutofacConfigurator
{
public static void Configure()
{
var builder = new ContainerBuilder();
...
builder.RegisterType<MyFormValidator>()
.Keyed<IValidator>(typeof(IValidator<MyForm>))
.As<IValidator>()
// 2nd parameter returns IQueryable<User>
.WithParameter("users", new SqlRepository<User>(dataContext))
.InstancePerRequest();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Register the validator factory with FluentValidation, and register
// FluentValidation as the model validator provider for the MVC framework.
// see http://www.jerriepelser.com/blog/using-fluent-validation-with-asp-net-mvc-part-3-adding-dependency-injection
var fluentValidationModelValidatorProvider =
new FluentValidationModelValidatorProvider(
new DependencyResolverValidatorFactory(container));
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
fluentValidationModelValidatorProvider.AddImplicitRequiredValidator = false;
ModelValidatorProviders.Providers.Add(fluentValidationModelValidatorProvider);
}
}
Getting the following exception:
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
I have other validators, most of which will not need data injected into them.
This is largely new ground for me (in both Autofac and FluentValidation) and am still trying to understand what I am doing here. I suspect I'm simply registering my type incorrectly. How do I fix this and properly register my type?
(My apologies if this is too similar to other questions that were already asked.)
I have zero experience with FluentValidation, but I doubt it's the cause of your issues anyway, so I'll plow forward regardless.
The exception you're getting means that Autofac can't resolve your service as 'instance per request'. There's a lot of documentation as to what this means on the Autofac documentation page. To summarize, it means that Autofac will attempt to resolve the service from a lifetime scope that is automatically created for each request sent to the webserver. When you register something as .InstancePerRequestScope() but then attempt to resolve that service outside of that scope, you'll get the DependencyResolutionException you see.
So we've established that your MyFormValidator isn't being resolved from a 'Request' scope. Why?
The custom DependencyResolverValidatorFactory you've written takes the actual IContainer that was built by Autofac, and resolves from that. This is a special type of ILifetimeScope, the 'root scope'. There's no request lifetime scope directly associated with this, so you get your exception. You need to to resolve from an ILifetimeScope that is began from the 'request' scope, or a sub-scope that is contained within the request scope.
The Autofac/MVC integration already automatically hosts a request scope (within the AutofacDependencyResolver, see the source), but your custom DependencyResolverValidatorFactory doesn't resolve from it. If you want to do that, I suppose you could modify your DependencyResolverValidatorFactory to accept the AutofacDependencyResolver instance instead, and use that to resolve.
It would look something like this:
public class DependencyResolverValidatorFactory : ValidatorFactoryBase
{
private readonly AutofacDependencyResolver resolver;
public DependencyResolverValidatorFactory(AutofacDependencyResolver resolver)
{
this.resolver = resolver;
}
public override IValidator CreateInstance(Type validatorType)
{
return resolver.RequestLiftimeScope.ResolveOptionalKeyed<IValidator>(validatorType);
}
}
Note the RequestLifetimeScope stuck in there.
Then you create this in your .Configure() method using
var resolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(resolver);
var fluentValidationModelValidatorProvider =
new FluentValidationModelValidatorProvider(
new DependencyResolverValidatorFactory(resolver));
That should get rid of the exception, assuming that this factory does indeed have a request to work from when creating instances of IValidators. If not, You might need to register using the default behavior (.InstancePerDependency(), where it creates a new instance every time it's requested) or a singleton (.SingleInstance()), depending on how/if validators can or should be shared.
Good luck.
I am just starting to learn Dependency Injection and I am stuck here.
My project has a WCF DataService over an Entity Framework DbContext.
public class MyDataService : DataService<MyDbContext>
{
protected override MyDbContext CreateDataSource()
{
// I want to use dependency injection for this
return new MyDbContext();
}
}
The class is either
a) IIS hosted, so I don't have any control
b) for integration tests, created with var host = new DataServiceHost(type, new Uri[] { });
both use different contstructors for MyDbContext
So basically to inject the Context with this
protected override MyDbContext CreateDataSource()
{
INinjectModule module = ???; // -
IKernel kernel = new StandardKernel(module);
return kernel.Get<MyDbContext>();
}
So the question is, what is best practice in this situation?
Should I:
a) Create a Module in a Class Library that both main projects and the service use
b) Create a public static Variable inside the DataService project that holds the Ninject module.
c) Create a public static Variable inside the DataService project that holds the Ninject kernel
d) Something else.
I would prefer something like
protected override MyDbContext CreateDataSource()
{
DefaultKernel.Get<MyDbContext>();
}
Firstly, you should have a Composition Root. That is, a single place where your Kernel is created (not in every single function).
Secondly, you don't need a NinjectModule here.. you're asking Ninject to create an instance of a concrete object (which in almost all circumstances.. defeats the purpose).
What you should create, is a separate NinjectModule pass it into the constructor of the Kernel.. something like this:
interface IContext {
}
class MyDbContext : DbContext, IContext {
}
class YourModule : NinjectModule {
protected override void Bind() {
Bind<IContext>().To<MyDbContext>();
}
}
// In your composition root somewhere
var kernel = new StandardKernel(new NinjectModule[] { new YourModule() });
// in your createdatasource method
kernel.Get<IContext>();
This will get you started. Normally, your composition root is what drives injection of objects throughout your application, thereby eliminating the need to pass the Kernel around (which you will have to do in your current setup).
The hard thing to understand when starting out with DI/IoC is that it is the container's job to create your entire dependency graph. Therefore, if you setup the following bindings:
IContract1 -> ConcreteObject1
IContract2 -> ConcreteObject2
IContract3 -> ConcreteObject3
..and have the following setup:
class ConcreteObject1 : IContract1 {
public ConcreteObject1(IContract2 contract3) {
}
}
class ConcreteObject2 : IContract2 {
public ConcreteObject2(IContract3 contract3) {
}
}
If you ask your container for a concrete implementation of IContract1 (which will be ConcreteObject1), then it will create it.... BUT: ConcreteObject1 requires a concrete implementation of IContract2 in the constructor. So the container says "Wait, I know how to create this".. and passes in an instance of ConcreteObject2. Again, it says "wait, ConcreteObject2 wants a concrete implementation of IContract3.. again, it goes and fetches one.
Hopefully that helps.