instruções simples sobre o controle .NET do reverso e Autofac

shanzm- 2020 Nian 3 Yue 16 Ri 02:17:35

1. Inversão de Controle

1.1 O que é um dependente?

Dependência de conceitos orientada por objectos são utilizados para descrever uma relação entre as classes e classe. Dois objectos externos, quando uma instância de objecto é responsável pela configuração de outro objecto, ou dependem dos serviços de outro objecto, principalmente entre dois objectos, tais como dependências

1.2 O que é inversão de controle?

Ele disse revertendo o primeiro a dizer, "forward", tradição, utilizando a nova palavra-chave com o construtor para criar um objeto no programa, que é um programa ativo para criar seus objetos dependentes, que é " Encaminhar ".

O chamador não criar um objeto que ele era o autor da chamada, mas por um terceiro (container) criado por um chamador objeto, um processo chamado de inversão de controle (Inversão de Controle, IOC ).

Por inversão de controle? Inversão de princípios de design de controle de programação orientada a objeto, pode ser usado para reduzir o grau de acoplamento entre o código de computador, fácil de expandir manutenção mais tarde.

1.3 Qual é a injeção de dependência?

O caminho principal para conseguir a inversão de controlo de injecção de dependência . (Naturalmente, este é mais do que uma injecção dependente método, bem como a pesquisa dependente (Dependência de pesquisa, DL), ambos referem-se a diferença entre: Definição: Inversão de Controle )

Dependência de injecção, em particular: chamar a classe não cria automaticamente um objecto dependente, mas o uso de recipientes para ajudar a criar e injectar objetos dependentes, este processo é chamado de injecção de dependência (dependência de injecção, DI )

Especificamente: um objecto do tipo Classe B Classe A (classe chamando) utilizado em (objetos dependentes), sob circunstâncias normais, usamos o objecto com a nova palavra-chave para criar um construtor na Classe A Classe B em

No entanto, depois de usar técnicas de DI, Classe A só precisa para definir uma propriedade do tipo Classe B, não esta necessidade ser obtido directamente novo objecto, mas o objecto será novos tipos de Classe B pelo COI recipiente para fora externamente e injectado em classe A, em referências a fim de alcançar classe a e classe B dissociação .

Resumo 1,4 breve

Veja os conceitos acima, pode-se observar que a frase " as dependências entre os módulos mencionados de dentro para fora do programa gerente instanciação chamada inversão de controle, este processo é chamado de injeção instanciação dependência ."




2. inversão do recipiente de controle

2.1 COI recipiente Descrição

Refere-se a "o uso de recipiente COI para criar objetos dependentes na chamada externa para a classe chamada e classe injetar" quando se trata de inversão de controle, onde os recipientes do COI são o quê?

COI recipiente é um recipiente que tem uma função de dependência injecção, instantiates recipiente COI, posicionamento, e as dependências de objetos entre objectos na configuração da aplicação. Assim, o pedido não precisa de novos objectos directamente relacionadas com o código de aplicação, o conjunto de pelo recipiente COI.

Em suma, o recipiente COI em duas funções principais: 1, e a relação de ligação entre a instância de serviço. 2, por exemplo, a criação e a destruição

No programa .NET muitos recipiente COI, como Unidade, Autofac, Spring.net como.

Diz-se Autofac sobre .NET maioria dos recipientes populares do COI, este artigo uma breve olhada Autofac de uso.

2.2 Introdução exemplo Autofac

recipiente Use Autofac é geralmente orientada interface de programação . Então, aqui utiliza um projeto hierárquico para demonstrar o uso Autofac, que uso Autofac criar um objeto de interface de classe

( Download Demo completa )

① Crie uma nova Biblioteca de classes projeto TestIBLL

Define a interface

public interface IUserBll
{
    //检查登录信息
    bool Login(string userName, string pwd);
    //添加新用户
    void AddNew(string userName, string pwd);
}

② criar uma nova classe biblioteca projecto TestBLLImpl

Adicione uma referência ao projeto TestIBLL para definição de interface classe de implementação

 public class UserBll : IUserBll
{
    //实现接口
    public void AddNew(string userName, string pwd)
    {
        Console.WriteLine($"新增了一个用户:{userName}");//为了演示,简单模拟
    }
    public bool Login(string userName, string pwd)
    {
        Console.WriteLine($"登录用户是:{userName}");//为了演示,简单模拟
        return true;
    }
}

[Descrição] :

Aqui definido UserBllclasse que implementa IUserBlla interface,

De acordo termo Autofac, seguinte endereço:

  • UserBllClasse chamado componente (Componente)

  • IUserBllInterface chamada Serviço (Service)

③ criar uma nova TestUI projeto de console

Simulação para a camada de IU

Adicione uma referência para projetos TestIBLL e TestBLLImpl

Instalação Autofac:PM>Install-Package Autofac

static void Main(string[] args)
{
    //创建容器构造者
    ContainerBuilder builder = new ContainerBuilder();
    //注册组件UserBll类,并把服务IUserBll接口暴露给该组件
    //把服务(IUserBll)暴露给组件(UserBll)
    builder.RegisterType<UserBll>().As<IUserBll>();
    //创建容器
    IContainer container = builder.Build();
    //使用容器解析服务,创建实例(不推荐,见下面说明):IUserBll userBll = container.Resolve<IUserBll>();
    //使用生命周期解析服务,创建实例
    using (ILifetimeScope scope = container.BeginLifetimeScope())
    {
        IUserBll userBll = scope.Resolve<IUserBll>();
        userBll.Login("shanzm", "123456");
    }

}    

[Descrição] :

  • Em que o termo em Autofac:

    • O contêiner (Container) : a estrutura do programa usado para gerenciar todos os componentes (significa simplesmente que todas as interfaces da classe de implementação)
    • Ciclo de Vida (Lifetime) : da criar uma instância da duração da liberação
    • Registration (Registro) : adicionar e configurar componentes para o comportamento recipiente
    • Âmbito (o escopo) : um contexto particular, em casos em que os outros componentes do conjunto serão baseados nos seus serviços partilhados
    • Resolução Serviço : serviço é equivalente ao instanciar um objeto
    • Register : Adicionando um serviço de implementos recipiente componente (classe de implementação) operação (Interface)
  • Ao criar um ContainerBuilderregisto componente

    ContainerBuilderHá uma série de método de registo usado aqui é de tipo de registro: RegisterType();

    Por qualquer RegisterType()registo de componentes deve ser um tipo específico de volta serviço de resolução quando, Autofac irá criar uma instância do objeto se registar

  • Cada componente é exposto a um ou mais de serviço (simplesmente é uma classe (conjunto) pode implementar uma ou mais interfaces de serviço ()), o seu uso como o método ContainerBuilder () para ligar entre si.

  • serviços de resolução, a criação de um serviço de fornecimento de um objeto (simplesmente significa que a interface é criada como uma classe de implementação registados)

    Não recomendado para usar o serviço recipiente direta para resolver:IUserBll userBll = container.Resolve<IUserBll>();

    Eu vi alguns artigos e vídeos usando o recipiente de serviço de resolução, mas eu li o documento oficial, que não é recomendado para tal uso, pois pode causar vazamentos de memória.

    Você sempre recomendado a partir de um serviço de análise de ciclo de vida (ou seja, o meu exemplo do caminho), para garantir que a instância do serviço está devidamente liberado e coleta de lixo

    documento Autofac: " Para sempre âmbito de um serviço de análise de ciclo de vida, em vez da partir do contêiner raiz! "

    Siga o bem de código de exemplo brevidade, eu uso serviço de contentores direta para resolver, sabe-se!




3 Use Autofac alguns detalhes

Autofac abaixo mostrar-lhe algumas das mais API básica, detalhes específicos e outras funções, consulte o documento Autofac, sua documentação é muito detalhado e há versão chinesa ( documento Autofac )

3.1 preparativos

Em seguida, o exemplo acima, adicione o seguinte itens biblioteca de interface TestIBLL em que:

criando IAnimalBll.cs

//IAnimalBll接口
public interface IAnimalBll
{
    void Cry();//动物都有叫的动作
}

criando IMasterBll.cs

//IMasterBll接口
public interface IMasterBll
{
    void Walk();
}

Nas interfaces acima descritos são implementados nos TestBLLImpl projeto de biblioteca de classe

criando DogBll.cs

//DogBll类实现IAnimalBll接口
public class DogBll : IAnimalBll
{
    public void Cry()
    {
        Console.WriteLine("汪汪汪!");
    }
}

criando CatBll.cs

//CatBll类实现IAnimalBll接口
public class CatBll : IAnimalBll
{
    public void Cry()
    {
        Console.WriteLine("喵喵喵!");
    }
}

criando MasterBll.cs

//MasterBll类,实现了IMasterBll接口和IUserBll接口
public class MasterBll : IMasterBll,IUserBll
{
    //注意这里,MasterBll是接口的实现类,这个类还有一个接口类型的属性
    public IAnimalBll dogBll { get; set; }

    public void AddNew(string userName, string pwd)
    {
        Console.WriteLine($"新增了一个Master用户:{userName}");
    }
    public bool Login(string userName, string pwd)
    {
        Console.WriteLine($"登录用户是Master:{userName}");
        return true;
    }
    public void Walk()
    {
        Console.WriteLine("带着狗散步!");
        dogBll.Cry();//在调用中,使用.PropertiesAutowired()方法给dogBll注册其实现类
    }
}


3.2 Todos registrado classe de implementação de todo o conjunto

Projeto, de fato, podemos usar .RegisterAssemblyTypes()uma interface única para todas as classes de montagem (classe projeto de biblioteca) estão registrados para a interface apropriada

static void Main(string[] args)
{
    ContainerBuilder builder = new ContainerBuilder();//创建容器构造者

    Assembly asm = Assembly.Load(" TestBLLImpl");//获取指定的程序集
    
    builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces();//注册指定程序集中的所有接口实现类

    IContainer container = builder.Build();//创建容器

    IUserBll userBll = container.Resolve<IUserBll>();//解析服务,创建实例

    userBll.Login("shanzm", "123456");//使用服务提供者
}

[Descrição] :

  • Sobre o uso .RegisterAssemblyTypes()do especificado montagem varredura registro, uso Where()e Except()tipo de filtrar
    o uso específico podem visualizar o documento: varredura Assembléia

  • .AsImplementedInterfaces(): O foco do registro da classe implementação do programa a todas as interfaces que implementa.


atributos de tipo de interface de classe de interface 3,3 injecção

As propriedades da classe aplicação também pode ser utilizado Autofac injectado,

Para a implementação de classe se houver uma interface em um tipo de interface de propriedade, podemos usar .PropertiesAutowired()o registo, enquanto a classe de implementação, enquanto o registro do imóvel, ou seja, para atingir propriedades de montagem automática, ou seja, propriedades injeção

static void Mian(string[] args)
{
    
    ContainerBuilder builder = new ContainerBuilder();

    Assembly asm = Assembly.Load("TestBLLImpl");

    //在这里通过.PropertiesAutowired(),给接口实现类中的接口属性也注册一个该类型的接口的实现类,即实现属性自装配
    builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired();
    builder.RegisterType<DogBll>().As<IAnimalBll>();

    IContainer container = builder.Build();

    IMasterBll masterBll = container.Resolve<IMasterBll>();
    masterBll.Walk();//打印:带着狗散步!汪汪汪!
}
  • Note-se que um detalhe, em MasterBlluma classe IAnimalBlltipo de atributo dogBll, que utilize PropertiesAutowired()um método de montagem propriedades automaticamente,

    No entanto morrer, interface de IAnimalBll TestBLLImpl程序集existem duas classes de implementação, a fim de montar automaticamente o registo atributo dogBll é o tipo de objeto CatBll

    E a minha expectativa é de tipos objeto DogBll registrados em tipos de propriedades para IAnimalBll

    Então, aqui também mostra o registro da classe DogBll para IAnimalBll interface

  • Se você sabe de antemão o nome eo valor da propriedade, você pode usarWithProperty("PropertyName", propertyValue)

    Então, um exemplo poderia escrever:

    builder.RegisterType<MasterBll>().As<IMasterBll>().WithProperty("dogBll",new DogBll());


Cerca de 3,4 interface tem um número de diferentes classes de implementação

Chegou o tempo para o registro para a classe implementação da interface, pode ter várias implementações da classe de interface, então nós podemos fornecer para cada nome registrado foi dada
builder.RegisterType<Object>().Named<IObject>(string name)
no momento do serviços de resolução, que pode ser criado através da especificação do provedor de serviço de nome (a classe de implementação)
IContainer.ResolveNamed<IObject>(string name)

static void Main(string[] args)
{
    ContainerBuilder builder = new ContainerBuilder();

    //builder.RegisterType<DogBll>().As<IAnimalBll>();//这样写,下面注册服务的时候,你只能给IAnimalBll对象创建一个DogBll类型的实例
    builder.RegisterType<DogBll>().Named<IAnimalBll>("Dog");
    builder.RegisterType<CatBll>().Named<IAnimalBll>("Cat");

    IContainer container = builder.Build();

    using (ILifetimeScope scope = container.BeginLifetimeScope())
    {
        IAnimalBll dogBll = scope.ResolveNamed<IAnimalBll>("Dog");
        IAnimalBll catBll = scope.ResolveNamed<IAnimalBll>("Cat");
        dogBll.Cry();
        catBll.Cry();
    }
}

No entanto, registramos todo o conjunto da classe de implementação quando o registro foi como diferentes implementações da classe de interface para ele?

usoIEnumerable<IObject> objects =container.Resolve<IEnumerable<IObject>>()

static void Main(string[] args)
{
    ContainerBuilder builder = new ContainerBuilder();

    Assembly asm = Assembly.Load(" TestBLLImpl");
    builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces();
    IContainer container = builder.Build();
    
    //解析服务,将所有实现了IAnimalBll接口的类都注册,结果存放在集合中
    IEnumerable<IAnimalBll> animalBlls = container.Resolve<IEnumerable<IAnimalBll>>();

    foreach (var bll in animalBlls)
    {
        Console.WriteLine(bll.GetType());
        bll.Cry();
    }
    //选取指定的实现类
    IAnimalBll dogBll = animalBlls.Where(t => t.GetType() == typeof(DogBll)).First();
    dogBll.Cry();
}


Cerca de 3,5 para atingir uma classe implementa várias interfaces

Antes de dizermos quando usado no componente de registro, um componente exposto a vários serviços, você pode usar o contínuo .As()método

Use .AsImplementedInterfaces()pode conseguir o mesmo efeito

MasterBll classe implementa várias interfaces, podemos registrar a interface de classe para todas as suas
palavras, enquanto as interfaces MasterBll implementado, temos registrado um MasterBll dar-lhe um objeto do tipo
Note, no entanto, que MasterBll objeto possui apenas a interface atual o método

static void Mian(string[] args)
{
     ContainerBuilder builder = new ContainerBuilder();

    //builder.RegisterType<MasterBll>().As<IUserBll>().As<IMasterBll>(); 
    //即一个组件暴露了多个服务,这里就等价于:
    builder.RegisterType<MasterBll>().AsImplementedInterfaces();//把MasterBll类注册给所有他实现的接口
   
    
    IContainer container = builder.Build();

    //解析IUserBll服务
    //其实这里的userBll是MasterBll类型的对象,但是这个MasterBll类型的对象只具有IUserBll接口中的方法,不具有IMasterBll接口中的方法
    IUserBll userBll = container.Resolve<IUserBll>();

    userBll.Login("shanzm", "11111");//打印:登录用户是Master:shanzm
    Console.WriteLine(userBll.GetType());//打印:TestBLLImpl.MasterBll
    //userBll.Walk();//注意虽然是MasterBll类型对象,但是只具有当前解析的IUserBll接口中的方法
}

[Descrição] :

  • O uso contínuo no momento da componente de inscrição (a classe de implementação) do As()método, pode expor todas as interfaces (serviços) a sua implementação, muito trabalho, então use o .AsImplementedInterfaces()método para implementar todas as interfaces registradas para alcançar sua classe

  • A classe de implementação implementa várias interfaces, mas na hora de serviços de resolução, com único método actualmente o interface sem solução.


3.6 para exemplos de âmbitos

Ao usar Autofac, os serviços finais de resolução, criar uma instância dos serviços oferecidos

O comprimento de tempo que o objeto existe no programa, que é a última versão do instanciado em tempos, chamado o serviço de ciclo de vida ,

Os objetos no aplicativo pode ser compartilhada com outros componentes e alcance do consumidor, chamado o serviço de escopo

Após a compreensão dos conceitos acima, podemos explicar o que é o exemplo do escopo

1. Um exemplo de uma dependência (instância por Dependência)

Quando chamamos o Resolve () retorna uma instância de serviços analíticos, cada solicitação retorna uma instância única, sem explicação, este é o escopo padrão!

static void Mian(string[] args)
{
    ContainerBuilder builder = new ContainerBuilder();
    //注册实例
    //builder.RegisterType<UserBll>().As<IUserBll>().InstancePerDependency(); //默认就是这种
    builder.RegisterType<UserBll>().As<IUserBll>();
    //创建容器
    IContainer container = builder.Build();
 
   //解析服务
    using (var scope = container.BeginLifetimeScope())
    {
        IUserBll userBll1 = scope.Resolve<IUserBll>();
        userBll1.Login("shanzm", "1111");//打印:登录用户是普通用户:shanzm
        IUserBll userBll2 = scope.Resolve<IUserBll>();
        userBll2.Login("shanzm", "2222");//打印:登录用户是普通用户:shanzm
        
        Console.WriteLine(ReferenceEquals(userBll1, userBll2));//打印结果:false
    }
}
//说明:根据调试,结果就可以看出,每次在解析服务,创建的服务提供者都是新的。
//你要注意,我们上面的示例代码在同一个生命周期中注册的两个IUserBll接口的实例,但是它们依旧是两个不同的实例

Exemplo 2. (Individual Instância)

É também chamado 'concretização único.' Âmbito exemplo único, todas as solicitações na raiz e todos os recipientes são âmbitos aninhados irá devolver o mesmo exemplo.

recomendações de interface de programação orientada, âmbito exemplos empregue: uma única instância. Impedir o funcionamento simultâneo, resultando em sujo!

static void Mian(string[] args)
{
    ContainerBuilder builder = new ContainerBuilder();
    //注册实例
    builder.RegisterType<UserBll>().As<IUserBll>().SingleInstance();//设置为单一实例
    //创建容器
    IContainer container = builder.Build();
 
    //解析服务
    using (var scope1 = container.BeginLifetimeScope())
    {
        IUserBll userBll1 = scope1.Resolve<IUserBll>();
        userBll1.Login("shanzm", "1111");
        using (var scope2 = container.BeginLifetimeScope())
        {
            IUserBll userBll2 = scope2.Resolve<IUserBll>();
            userBll2.Login("shanzm", "2222");
            Console.WriteLine(ReferenceEquals(userBll1, userBll2));
            //因为是单一实例,所以就是在不同的生命周期中,也是同一个实例,打印结果:true
        }
    }
}
//说明:最终的打印结果:true 。即使在不同的生命周期中每次在解析服务,创建的服务提供者都是同一个!

Outros exemplos de alcance, a referência pode ser documentação: Exemplo Âmbito

  1. Cada instância do ciclo de vida de um escopo (instância por Lifetime Âmbito)
  2. Cada combinando um exemplo âmbito do ciclo de vida (instância por condizer Lifetime Âmbito)
  3. Cada instância de um pedido (Instância por solicitação)
  4. Instância cada vez tem um (instância por Owned)
  5. fio de escopo (Tópico Âmbito)




4. Autofac no MVC

Autofac mais conveniente para usar em ASP .NET MVC, o lugar principal é na necessidade de atenção arquivo de configuração Global.asax.cs para Autofac

Faça um exemplo simples :( clique para baixar o código-fonte completo de demonstração )

① Criar um projeto de biblioteca de classe chamado TestIService, a definição de todas as interfaces

Criar um arquivo IUserService.cs

public interface IUserService
{
    bool CheckLogin(string userName, string pwd);
    bool CheckUserNameExists(string userName);
}

Criar um arquivo INewsService.cs

public interface INewsService
{
    string AddNews(string title, string body);
}

② Criar um projeto de biblioteca de classe chamado TestServiceImpl alcançar interface de definição de classe

Primeiro, adicione uma referência para o TestIService projeto

Criar um arquivo UserService.cs

public class UserService : IUserService
{
    //注意接口的实现类是可以有接口类型的属性,该属性也会被注册一个实现对应类型接口的类的对象
    public INewsService newsService { get; set; }
    public bool CheckLogin(string userName, string pwd)
    {
        return true;
    }
    public string UserAction(string userName)
    {
        string result = newsService.AddNews("2020年3月16日-新冠病毒", "中国境内的新冠病毒被有效遏制");
        return userName+"  添加新闻  :"+result;
    }
}

Criar um arquivo NewsService.cs

public class NewsService : INewsService
{
    public string AddNews(string title, string body)
    {
        return ($"Title:{title},Content:{body}");
    }
}

③ criar um projeto Web MVC chamado TestMVC

Primeiro, adicione uma referência aos projectos e projectos TestIService TestServiceImpl

Em seguida, instalar o plug-in MVC Autofac:PM> Install-Package AutoFac.Mvc5

Adicionar configuração Autofac em Global.asax.cs em:

using Autofac.Integration.Mvc;

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RouteConfig.RegisterRoutes(RouteTable.Routes);

    /*------------------------------AutoFac配置--开始--------------*/

    ContainerBuilder builder = new ContainerBuilder();
    //此处需要:using Autofac.Integration.Mvc;
    //把当前程序集中的所有Controllerr类中的接口类型的属性注册
    builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

    Assembly asmSevice = Assembly.Load("TestServiceImpl");
    builder.RegisterAssemblyTypes(asmSevice)
        .Where(type => !type.IsAbstract)//除去抽象类,抽象类不可以实例化(其实这一句也可以不写)
        .AsImplementedInterfaces()//将实现类注册给其实现的所有接口
        .PropertiesAutowired();//接口实现类中接口类型的属性也注册
    IContainer container = builder.Build();
    //MVC中的所有Controller类都是由AutoFac帮我们创建对象
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

    /*------------------------------AutoFac配置--结束--------------*/
}

Criando controlador HomeController.cs

public class HomeController : Controller
{
    public IUserService userService { get; set; }//通过AutoFac自动为我们赋值一个IUserService接口实现对象


    public ActionResult CheckLogin()
    {
        bool b = userService.CheckLogin("shanzm", "123456");
        return Content(b.ToString());//结果:页面显示true
    }

    public ActionResult UserAddNews()
    {
        string result = userService.UserAction("shanzm");
        return Content(result);//结果:页面显示:shanzm 添加新闻 :Title:2020年3月16日-新冠病毒,Content:中境内的新冠病毒被有效遏制
    }
}

Nos solicitações do navegador foram HomeController dois ação, isto é, você pode ver que nós usamos Autofac UserService para injetar o sucesso atributo instância apropriada!




A referência e amostras de downloads de código fonte

Baixe o exemplo de código fonte completo

Documentação: Autofac documentos oficiais chineses

Parque blog: uma compreensão abrangente da injeção de dependência ASP.NET Núcleo

Parque blog: Autofac Raiders do ASP.NET MVC do COI

Parque blog: componentes Autofac, serviços de montagem automatizada "o segundo"

Jane livro: uso Autofac

Acho que você gosta

Origin www.cnblogs.com/shanzhiming/p/12501543.html
Recomendado
Clasificación