📜 ⬆️ ⬇️

Dependency injection in the MVC 3 Framework by the example of Autofac

It is currently difficult to imagine an application on MVC3Framework without using Dependency injection. This article is intended for those who know what DI is, but have never used Autofac for this.
Also note that in more detail about Autofac you can read here.

First we need to download and include the Autofac libraries in the project. For this, I use NuGet. Type in the console:
PM> Install-Package Autofac Install Autofac yourself
PM> Install-Package Autofac.Mvc3 And additions to Mvc3

You can also use NuGet's visual editor, or simply download and connect these assemblies.
The following code is written to initialize Autofac, I tried to include the main initialization options here.

 protected void Application_Start() { Trace.TraceInformation("Website initialization started"); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); // Setup IoC container var builder = new ContainerBuilder(); builder.RegisterModule(new ServicesModule()); builder.Register(c => new Entities()).As<IEntities>() .OnActivated(e => { var config = DependencyResolver.Current.GetService<IGlobalSettings>(); e.Instance.RawConnectionString = config.Data.SqlServerConnectionString; }).InstancePerHttpRequest(); builder.RegisterType<LocalizationContext>().PropertiesAutowired().InstancePerHttpRequest(); builder.Register(c => new DefaultGlobalSettings()).As<IGlobalSettings>().SingleInstance(); builder.RegisterGeneric(typeof(MongoRepository<>)) .As(typeof(IMongoRepository<>)).InstancePerHttpRequest(); builder.Register(c => EnvironmentContext()).As<IEnvironmentContext>().InstancePerHttpRequest(); builder.RegisterModule(new AutofacWebTypesModule()); builder.RegisterSource(new ViewRegistrationSource()); builder.RegisterModelBinders(Assembly.GetExecutingAssembly()); builder.RegisterModelBinderProvider(); builder.RegisterFilterProvider(); IContainer container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); Trace.TraceInformation("Website has been successfully initialized"); } 

')
Now consider what actually happened here.
Registering a module for Autofac. This is very useful for initializing classes (classes with the access modifier internal) that are in a separate assembly. We just have to leave ServicesModule in the same assembly, and enjoy all the delights of DI
  builder.RegisterModule(new ServicesModule()); 

The method that must be performed to obtain the required object can be specified as follows:
  builder.Register(c => EnvironmentContext()).As<IEnvironmentContext>().InstancePerHttpRequest() 

The same but in the form of an anonymous delegate.
  builder.Register(c => new Entities()).As<IEntities>() .OnActivated(e => { var config = DependencyResolver.Current.GetService<IGlobalSettings>(); e.Instance.RawConnectionString = config.Data.SqlServerConnectionString; }).InstancePerHttpRequest(); 

You can compare the class with the interface as follows:
  builder.Register(c => new DefaultGlobalSettings()).As<IGlobalSettings>().InstancePerHttpRequest(); 

In order to register Generic classes, use the following code:
  builder.RegisterGeneric(typeof(MongoRepository<>)) .As(typeof(IMongoRepository<>)).InstancePerHttpRequest(); 

In order to inject properties of a class, it is enough to do the following initialization. I note that the DI in the constructor is much faster than on the property, so such an injection should be used only in extreme cases.
  builder.RegisterType<LocalizationContext>().PropertiesAutowired().InstancePerHttpRequest(); 

If the property is known in advance, you can use this initialization:
  builder.Register(c => new LocalizationContext { GlobalSettings = c.Resolve<IGlobalSettings>() }); 

Initialization of the classes HttpContextBase, HttpRequestBase, HttpResponseBase, HttpServerUtilityBase, HttpSessionStateBase, HttpApplicationStateBase, HttpBrowserCapabilitiesBase, HttpCachePolicyBase, VirtualPathProvider is in place;
  builder.RegisterModule(new AutofacWebTypesModule()); 

Autofac allows injection in ModelBinder.
  builder.RegisterModelBinders(Assembly.GetExecutingAssembly()); builder.RegisterModelBinderProvider(); 

Injection into filters (classes derived from ActionFilterAttribute) is as follows:
  builder.RegisterFilterProvider(); 

Injection in the View is the registration of the next module.
  builder.RegisterSource(new ViewRegistrationSource()); 

As you noticed, the code is accompanied by a call:
.InstancePerDependency () - used by default, creates a new object with each call.
.InstancePerHttpRequest () is a single instance on HttpRequest
.SingleInstance () - creates only one instance of the class.
.InstancePerLifetimeScope () - creates an instance for a specific LifetimeScope is used as follows:
 using (var lifetime = container.BeginLifetimeScope()) { var component = lifetime.Resolve<SomeComponent>(); // component, and any of its disposable dependencies, will // be disposed of when the using block completes } 

We receive a copy of the container.
  IContainer container = builder.Build(); 

Install DependencyResolver
  DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 


That's all. Now you have the minimum skills to work with autofac, and you can safely begin to use it in your project. It was quite difficult for me to pick out exactly those moments that would help you master Autofac in a short time. If I haven't covered any topic enough: please write it down in the comments.

Source: https://habr.com/ru/post/136895/


All Articles