anuário
- 1. Inversão de Controle
- 2. inversão do recipiente de controle
- 3 Use Autofac alguns detalhes
- 3.1 preparativos
- 3.2 Todos registrado classe de implementação de todo o conjunto
- atributos de tipo de interface de classe de interface 3,3 injecção
- Cerca de 3,4 interface tem um número de diferentes classes de implementação
- Cerca de 3,5 para atingir uma classe implementa várias interfaces
- 3.6 para exemplos de âmbitos
- 4. Autofac no MVC
- A referência e amostras de downloads de código fonte
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
① 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 UserBll
classe que implementa IUserBll
a interface,
De acordo termo Autofac, seguinte endereço:
UserBll
Classe chamado componente (Componente)IUserBll
Interface 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
ContainerBuilder
registo componenteContainerBuilder
Há 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 registarCada 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, usoWhere()
eExcept()
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
MasterBll
uma classeIAnimalBll
tipo de atributodogBll
, que utilizePropertiesAutowired()
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 CatBllE 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 usar
WithProperty("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 classeA 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
- Cada instância do ciclo de vida de um escopo (instância por Lifetime Âmbito)
- Cada combinando um exemplo âmbito do ciclo de vida (instância por condizer Lifetime Âmbito)
- Cada instância de um pedido (Instância por solicitação)
- Instância cada vez tem um (instância por Owned)
- 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"