Autofac - resolve before build - c#

With Unity dependency can be resolved before the container is build. Is that possible with Autofac as well?
Below code demonstrates my scenario - I'd need to resolve the ICacheRepository in order to "new up" the singleton CacheHelper.
In Unity that would be simply done with container.Resolve<ICacheRepository>() in the place of ???. What about in Autofac?
var builder = new ContainerBuilder();
builder.RegisterType<CacheRepository>().As<ICacheRepository>();
var cacheHelper = new CacheHelper(???);
builder.RegisterInstance(cacheHelper).As<CacheHelper>();
Where CacheHelper class has a constructor dependency on CacheRepository.
public class CacheHelper
{
private readonly ICacheRepository _repository;
public CacheHelper(ICacheRepository repository)
{
_repository = repository;
}
}

You should not have to resolve component during build process. Autofac is able to solve object graph dependency. In your case CacheHelper depends on ICacheRepository so you just have to register CacheHelper and ICacheRepository
var builder = new ContainerBuilder();
builder.RegisterType<CacheRepository>().As<ICacheRepository>();
builder.RegisterType<CacheHelper>().As<CacheHelper>();
When Autofac will resolve CacheHelper it will create the dependency graph and create the instance of CacheHelper with an instance ofsi ICacheRepository. If you need to have a Singleton you can tell Autofac to create only a single instance.
var builder = new ContainerBuilder();
builder.RegisterType<CacheRepository>().As<ICacheRepository>();
builder.RegisterType<CacheHelper>().As<CacheHelper>().SingleInstance();
Another solution would be register lambda expression, these registrations are called when you need it, so you can resolve things during build process :
var builder = new ContainerBuilder();
builder.RegisterType<CacheRepository>().As<ICacheRepository>();
builder.Register(c => new CacheHelper(c.Resolve<ICacheRepository>()))
.As<CacheHelper>()
.SingleInstance(); // It will result of having one CacheHelper whereas
// ICacheRepository is declared as .InstancePerDependency
Be careful with this solution because ICacheRepository is declared without scope the InstancePerDependency scope will be used by default. Because CacheHelper is SingleInstance only a single instance of ICacheRepository will be used which may result to bugs. See Captive Dependency for more information.
In your case, it doesn't seem like you need this kind of registration.

Related

Which lifecycle is best for using Entity Framework with Autofac in ASP.Net MVC?

I am new to Autofac and I am using it as a dependency container. I want to register my DB context. This is what I've done
public static class AutofacConfig
{
public static void RegisterComponents()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyEntities>().As<IMyEntities>().SingleInstance().PreserveExistingDefaults();
var container = builder.Build();
GlobalConfiguration.Configuration.UseAutofacActivator(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
But In .net Core, I need to register my DBContext as Scoped. Is it correct to register my Entities here as SingleInstance or I should change it?
According to MS docs here "A DbContext instance is designed to be used for a single unit-of-work." From experience I've found registering a DBContext as a SingleInstance often leads to difficult to reproduce exceptions, especially in a multi threaded environment.
I would consider giving it as smaller scope as possible to achieve a unit of work, such as InstancePerLifetimeScope

How do IoC controllers actually work? Specifically in .NET MVC?

Controller Constructor:
IRestaurantData db;
public HomeController(IRestaurantData db)
{
this.db = db;
}
// Container code
public class ContainerConfig
{
internal static void RegisterContainer(HttpConfiguration httpConfiguration)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterApiControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<InMemoryRestaurantData>()
.As<IRestaurantData>()
.SingleInstance();
var container = builder.Build();
// MVC CONTROLLER VERSION
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// WEBAPI CONTROLLER VERSION
httpConfiguration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
So I'm trying to wrap my head around how Inversion of Control containers work. The course I'm in is using Autofac to create these containers. From what I'm currently understanding creating this container is making it so that when I instantiate my HomeController with IRestaurantData the container is pointing the interface AT InMemoryResataurantData everytime it is used. I can understand that much. What Im also confused by is I dont understand WHERE in the program my Controllers are are actually being instantiated? Does anyone know?
That is being done by autofac. whenever you request a class from a container, it will instantiate the type for you using the default constructor. If you have a constructor with parameters, it will look in the container for other registered types and will instantiate a new object or fetch an already used object.
Your instantiated types can be transient (short lived) or not.
So in short; when the object is requested.

Trying to inject a mocked instance in a test class with autofac, but the container is injecting the same instance in other test classes

I'm trying to resolve a handler to my test using autofac, then i'm injecting a mocked instance of it in that way:
_mockedHandlerInstance = new TestHandler(_repository.Object, _mediator.Object, _logger.Object);
containerBuilder.RegisterInstance(_mockedHandlerInstance).As<HandlerToProcess>();
The same container is created in a TestBase class that is inherited in other test classes, but when i try to use something related with the HandlerToProcess the container return the same instance that i've created and mocked before in the class above.
So, what i need is to create a specific mock of this handle for each class and use autofac to inject them, do you guys know anyway to do this?
The TestBase class just initialize the container and register a few asseblies:
Settings.LoadConfigContext("configurationSettings");
EffortProviderFactory.ResetDb();
_containerBuilder = new ContainerBuilder();
var assemblies = new Assembly[]
{
typeof(AppModule).Assembly,
typeof(Repository).Assembly,
};
_containerBuilder.RegisterModule(new AutofacModule(assemblies));
I'm also using Effort, but i don't think this could cause the problem.

sample example about Dependency injection needs explanation

I was going through this article about dependency injection http://www.asp.net/web-api/overview/advanced/dependency-injection
It shows Unity Container from Microsoft.
There are a few things that are not making sense to me
for example, following line
public ProductsController(IProductRepository repository)
The above is the constructor of Controller. I need to know who passes the repository to the constructor? ANd is that made possible by registering IProductRepository interface with Unity?
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Other Web API configuration not shown.
}
Is the above code is all needed to make MVC pass the object to the constructor of a controller?
You answered your own question:
is that made possible by registering IProductRepository interface with Unity?
Yes.
When you request to resolve a type using Unity, the container searches for public constructors. If the constructor needs some implementation (IProductRepository in your case), the container searches within its registrations for an implementation for all the needed parameters. If found, it resolves that. This is a recursive process.
So yes. You need to register an implementation of IProductRepository using the container in order to resolve an instance of the Controller using that container.

Autofac RegisterInstance vs SingleInstance

IProductRepositoryProxy ProductDataServiceProviderInstance = new ServiceProductDataProvider();
builder.RegisterInstance(ProductDataServiceProviderInstance).As<IProductRepositoryProxy>();
VS
builder.RegisterType<ServiceProductDataProvider>().As<IProductRepositoryProxy>().InstancePerRequest();
I saw this code from an ex-employee here and wonder if the guy wanted to register a .SingleInstance() behavior.
builder.RegisterType<ServiceProductDataProvider>().As<IProductRepositoryProxy>().SingleInstance();
Is the manual newing-up of the ServiceProductDataProvider with RegisterInstance not the same as the Register .SingleInstance() ??
Is the manual newing-up of the ServiceProductDataProvider with RegisterInstance not the same as the Register .SingleInstance() ??
The RegisterInstance allows you to register a single instance in AutoFac.
The difference between RegisterInstance and RegisterType + SingleInstance methods is that the RegisterInstance method allows you to register an instance not built by Autofac.
But both solution will result in registering a singleton in Autofac.
By the way, both registration are equivalent in the following code sample
var instance = GetInstanceFromSomewhere();
builder.RegisterInstance<IService>(instance);
builder.Register(c => instance).As<IService>().SingleInstance();

Categories