Árvore de páginas

Você está vendo a versão antiga da página. Ver a versão atual.

Comparar com o atual Ver Histórico da Página

« Anterior Versão 3 Próxima »

Framework de DI

Existem muitas estruturas/frameworks de injeção de dependência que automatizam a resolução de dependências. Eles podem criar objetos com todas as dependências (e dependências de dependências recursivamente). Então, basta escrever sua classe com padrões de injeção de construtor e/ou propriedades que o framework de DI lida com o resto! Em uma boa aplicação, suas classes são independentes mesmo do framework DI. Haverá algumas linhas de código ou classes que interagem explicitamente com o framework DI em toda a sua aplicação. O TNF usa a estrutura do Castle Windsor para Injeção de Dependência. É um dos Frameworks de DI mais maduros. 

 

public class PersonAppService
{
    private IPersonRepository _personRepository;

    public PersonAppService(IPersonRepository personRepository)
    {
        _personRepository = personRepository;
    }

    public void CreatePerson(string name, int age)
    {
        var person = new Person { Name = name, Age = age };
        _personRepository.Insert(person);
    }
}

 

var container = new WindsorContainer();

container.Register(
        Component.For<IPersonRepository>().ImplementedBy<PersonRepository>().LifestyleTransient(),
        Component.For<IPersonAppService>().ImplementedBy<PersonAppService>().LifestyleTransient()
    );

var personService = container.Resolve<IPersonAppService>();
personService.CreatePerson("Yunus Emre", 19);

 

O TNF quase torna invisível o uso da estrutura de injeção de dependência ao escrever sua aplicação seguindo as práticas recomendadas e algumas convenções.

Registro de dependências por convenções

O TNF registra automaticamente todos os Repositórios, Serviços de Domínio, Serviços de Aplicação, Controladores MVC e Controladores da Web API por convenção. Por exemplo, você pode ter uma interface IPersonAppService e uma classe PersonAppService que implementa:


public interface IPersonAppService : IApplicationService
{
    //...
}

public class PersonAppService : IPersonAppService
{
    //...
}

 

O TNF registra automaticamente a classe que implementa a interface IApplicationService (É apenas uma interface vazia). Essa dependência é registrada como transient (instância criada por uso). Quando você injeta (usando a injeção do construtor) IPersonAppService interface para uma classe, um objeto PersonAppService é criado e passado para o construtor automaticamente.

O registro de dependência por convenções se dá pela configuração do módulo, onde no método Initialize conterá o seguinte trecho de código:


public class AppModule : TnfModule
{
    public override void Initialize()
    {
      IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
    }
}
Helper Interfaces

Você pode registrar uma classe especifica fazendo o uso de convenções através da herança das interfaces ITransientDependency e ISingletonDependency:

public interface IPersonManager
{
    //...
}

public class MyPersonManager : IPersonManager, ISingletonDependency
{
    //...
}


Registro de tipos de forma direta
Usando IocManager:

IocManager.Register<IMyService, MyService>(DependencyLifeStyle.Transient);


Usando o Castle Windsor API

Voce pode usar a propriedade IIocManager.IocContainer para acessar o Castle Windsor Container e registrar as dependências:

IocManager.IocContainer.Register(Classes.FromThisAssembly().BasedOn<IMySpecialInterface>().LifestylePerThread().WithServiceSelf());

 

Resolvendo dependências

Toda classe registrada no injetor de DI pode ser resolvida automaticamente através da injeção pelo construtor de uma classe ou usando o objeto de IocManager do TNF:

IMyService instance = IocManager.Resolve<IMyService>();

 

Existem cenários onde é necessário criar uma instancia e após seu uso realizar sua liberação. Para esses casos o objeto de IocManager possui métodos de extensão que possibilitam a criação e a liberação desses recursos:

public class MySampleClass : ITransientDependency
{
    private readonly IIocResolver _iocResolver;

    public MySampleClass(IIocResolver iocResolver)
    {
        _iocResolver = iocResolver;
    }

    public void DoIt()
    {
        // Resolving, using and releasing manually
        var personService1 = _iocResolver.Resolve<PersonAppService>();
        personService1.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" });
        _iocResolver.Release(personService1);

        // Resolving and using in a safe way
        using (var personService2 = _iocResolver.ResolveAsDisposable<PersonAppService>())
        {
            personService2.Object.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" });
        }
    }
}

 

No cenário acima foi realizada a injeção do objeto IIocResolver. O mesmo cenário pode ser criado usando diretamente o objeto IocManager como no exemplo abaixo:

using Tnf.Dependency;

 

public class MySampleClass : ITransientDependency
{
    public void DoIt()
    {
        // Resolving, using and releasing manually
        var personService1 = IocManager.Instance.Resolve<PersonAppService>();
        personService1.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" });
        _iocResolver.Release(personService1);

        // Resolving and using in a safe way
        using (var personService2 = IocManager.Instance.ResolveAsDisposable<PersonAppService>())
        {
            personService2.Object.CreatePerson(new CreatePersonInput { Name = "Yunus", Surname = "Emre" });
        }
    }
}


IShouldInitialize interface

Algumas classes precisam ser inicializadas antes da primeira utilização. A interface IShouldInitialize tem um método Initialize(). Se você implementá-lo, então o método Initialize() é chamado automaticamente apenas após a criação do objeto (antes usado).


  • Sem rótulos