How to Register these class In Autofac

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

Answers


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;
        }
    }


}

Need Your Help

Input Field, wrap text instead of extending horizontally

html css input text word-wrap

I have an input field, a user will write text inside but when the text is to long it just extends horizontally instead of dropping down vertically.

how to log Spring 5 WebClient call

java spring-boot logging spring-webflux

I'm trying to log a request using Spring 5 WebClient. Do you have any idea how could I achieve that?