How to Register these class In Autofac

30,997

EDIT: I misread this and thought it was a question about how to use autofac to register dependencies. If you want to keep the same UnitOfWork, you need to scope the lifetime of the instance to something. If you're using this in an ASP.NET or WCF application you can register your dependencies like this:

typeBuilder.RegisterType<UnitOfWork>().InstancePerLifetimeScope();
typeBuilder.RegisterType<Repository>();
typeBuilder.RegisterType<Service>();

First thing you need to do in order to use a container like Autofac is register all your dependencies. In Autofac you can do that a few ways but all of them rely on using the a ContainerBuilder. The ContainerBuilder relies on extension methods so make sure you have a using statement for the Autofac namespace.

You can explicitly define the factory methods:

// Explicitly 
var builder = new ContainerBuilder();
builder.Register<UnitOfWork>(b => new UnitOfWork());
builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>()));
builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>()));

Using ContainerBuilder we access the Register<>() method to provide the service interface (which is how we will be asking the container for the service) in this case, I'm not using interfaces, just the actual type. Any time you ask the container for a UnitOfWork it will use the factory method new UnitOfWork() to generate one. In real life, you would probably be asking for an IUnitOfWork. This can all be a bit verbose, but it's very handy when you need custom logic for dependency creation.

You can use the builder like any other dependency container and just register the types.

// Implicitly
var typeBuilder = new ContainerBuilder();
typeBuilder.RegisterType<UnitOfWork>();
typeBuilder.RegisterType<Repository>();
typeBuilder.RegisterType<Service>();

This approach relies on registering all the dependencies needed to build up a class. The container will then use reflection to resolve any constructor arguments. If an argument is not registered, the container will throw an exception with the type it could not resolve. In this case, the service has a dependency on UnitOfWork and Repository. Repository also has a dependency on UnitOfWork. These dependencies are expressed as constructor arguments. In order to request a Repository or a Service from the container, all dependencies must be registered

You can use the configuration approach.

If you're using an app.config file, you can define your config file like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
  </configSections>

  <autofac defaultAssembly="AutoFacTest">
    <components>
      <component
              type="AutoFacTest.Repository, AutoFacTest"
              service="AutoFacTest.Repository" />

      <component
               type="AutoFacTest.UnitOfWork, AutoFacTest"
               service="AutoFacTest.UnitOfWork" />

      <component
              type="AutoFacTest.Service, AutoFacTest"
              service="AutoFacTest.Service" />
    </components>
  </autofac>
</configuration>

First, notice that we have to define a config section (notice the <ConfigSections>). Then, we can create an <autofac> section that defines all our dependencies. The notation is pretty simple, you basically create a <component> for every dependency. Each component has a service attribute which defines the type that will be requested. There is also a type attribute that defines the object to be created when an instance of the service is requested. This is analogous to builder.Register<UnitOfWork>(b => new UnitOfWork()) where UnitOfWork is the service requested (and in this case) also the type to be created.

To create the builder using the configuration, use a ConfigurationSettingsReader()

// Config
var configBuilder = new ContainerBuilder();
configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac"));

You have to pass in the name of your configuration section (in this case, autofac). Once you've configured the dependencies, you have to build a container. The ContainerBuilder contains a method to do this:

var container = builder.Build();
var typeContainer = typeBuilder.Build();
var configContainer = configBuilder.Build();

And once you have the container, you can request instances of your service:

container.Resolve<Service>().DoAwesomeness();
typeContainer.Resolve<Service>().DoAwesomeness();
configContainer.Resolve<Service>().DoAwesomeness();

Complete program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autofac;
using Autofac.Configuration;

namespace AutoFacTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Explicitly 
            var builder = new ContainerBuilder();
            builder.Register<UnitOfWork>(b => new UnitOfWork());
            builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>()));

            builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>()));

            // Implicitly
            var typeBuilder = new ContainerBuilder();
            typeBuilder.RegisterType<UnitOfWork>();
            typeBuilder.RegisterType<Repository>();
            typeBuilder.RegisterType<Service>();

            // Config
            var configBuilder = new ContainerBuilder();
            configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac"));

            var container = builder.Build();
            var typeContainer = typeBuilder.Build();
            var configContainer = configBuilder.Build();


            container.Resolve<Service>().DoAwesomeness();
            typeContainer.Resolve<Service>().DoAwesomeness();
            configContainer.Resolve<Service>().DoAwesomeness();
            Console.Read();
        }
    }

    public class Repository
    {
        private readonly UnitOfWork _unitOfWork;
        public Repository(UnitOfWork uow)
        {
            _unitOfWork = uow;
        }

        public void PrintStuff(string text)
        {
            Console.WriteLine(text);
        }
    }

    public class Service
    {
        private readonly Repository _repository;
        private readonly UnitOfWork _unitOfWork;

        public Service(Repository repo, UnitOfWork uow)
        {
            _repository = repo;
            _unitOfWork = uow;
        }
        public void DoAwesomeness()
        {
            _repository.PrintStuff("Did awesome stuff!");
            _unitOfWork.Commit();
        }
    }

    public class UnitOfWork
    {
        public bool Commit()
        {
            return true;
        }
    }


}
Share:
30,997
DotDot
Author by

DotDot

I'am a Senior developer ,now work in Alibaba. I'am good at C#,java,Golang,html5,javascript. Experience in Java programming and in object-oriented software development,etc.CLEAR ARCHITECTURE,MVP,RXJAVA,OPENGL,OPENCV. An understanding of Android, with a focus on topics such as building custom UIs, network communication, data storage and performance. DianDianDhong app @ google play: https://play.google.com/store/apps/details?id=com.alibaba.android.babylon The Newest Version: http://sj.qq.com/myapp/detail.htm?apkName=com.alibaba.android.babylon

Updated on July 05, 2022

Comments

  • DotDot
    DotDot almost 2 years

    I am using autofac as Ioc Container. I have Three Classes:

    class Service
    {
         public Service(Repository rep,UnitOfWork context){}
    
    }
    
    Class Repository
    {
         public Repository(UnitOfWork context){}
    }
    
    class UnitOfWork{}
    

    the Service and Repository need the same instance of UnitOfWork

    How to do that? and How to wirte it in XmlConfiguration