Dependency injection in MVC 3 Framework using Autofac as an example

    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.
    I also note that you can read more about Autofac here.

    First we need to download and include Autofac libraries in the project. For this I use NuGet. Enter in the console:
    PM> Install-Package AutofacInstall Autofac itself
    PM> Install-Package Autofac.Mvc3And add-ons for Mvc3

    You can also use the NuGet visual editor, or just download and connect these assemblies.
    Below is the code for initializing Autofac, I tried to include the basic 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()
          .OnActivated(e =>
            {
              var config = DependencyResolver.Current.GetService();
              e.Instance.RawConnectionString = config.Data.SqlServerConnectionString;
             }).InstancePerHttpRequest();
      builder.RegisterType().PropertiesAutowired().InstancePerHttpRequest();
      builder.Register(c => new DefaultGlobalSettings()).As().SingleInstance();
      builder.RegisterGeneric(typeof(MongoRepository<>))
                 .As(typeof(IMongoRepository<>)).InstancePerHttpRequest();
      builder.Register(c => EnvironmentContext()).As().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 really happened here.
    Register the module for Autofac. This is very useful for initializing classes (classes with an internal access modifier) ​​that are in a separate assembly. It is enough for us to leave ServicesModule in the same assembly, and use all the delights of DI.
         builder.RegisterModule(new ServicesModule());
    

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

    Same thing as an anonymous delegate.
      builder.Register(c => new Entities()).As()
                 .OnActivated(e =>
                  {
                      var config = DependencyResolver.Current.GetService();
                       e.Instance.RawConnectionString = config.Data.SqlServerConnectionString;
                   }).InstancePerHttpRequest();
    

    You can map the class to the interface as follows:
      builder.Register(c => new DefaultGlobalSettings()).As().InstancePerHttpRequest();
    

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

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

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

    The initialization of the classes HttpContextBase, HttpRequestBase, HttpResponseBase, HttpServerUtilityBase, HttpSessionStateBase, HttpApplicationStateBase, HttpBrowserCapabilitiesBase, HttpCachePolicyBase, VirtualPathProvider autoformation occurs.
      builder.RegisterModule(new AutofacWebTypesModule());
    

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

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

    Injection into the View occurs by registering 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 () - one instance on HttpRequest
    .SingleInstance () - creates only one instance of the class.
    .InstancePerLifetimeScope () - creates an instance for a specific LifetimeScope used as follows:
    using (var lifetime = container.BeginLifetimeScope())
    {
      var component = lifetime.Resolve();
      // component, and any of its disposable dependencies, will
      // be disposed of when the using block completes
    }
    

    Get the container instance.
     IContainer container = builder.Build();
    

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


    That's all. Now you have minimal skills with autofac, and you can safely start using it in your projects. It was quite difficult for me to single out precisely those moments that would help you master Autofac in a short time. If I haven’t covered enough of a topic: please write it in the comments.

    Also popular now: