Pergunta

Eu tenho trabalhado através dos detalhes da implementação do COI nos meus aplicativos da Web, mas de uma maneira que aproveite o Microsoft.Practices.ServiceLocation. Estou usando especificamente o Autofac e a integração do ASP.NET, mas queria me deixar aberto para outros contêineres. Ao longo da linha de essa questão, eu estava preocupado com como acessar o contêiner no meu código de aplicativo da web.

Eu tenho uma biblioteca 'núcleo' que define principalmente interfaces a serem resolvidas. Esta biblioteca principal também é usada pelo meu aplicativo da web e outros aplicativos. Muito útil para ter interfaces comuns definidas. Eu pensei que este era um excelente lugar para colocar acesso ao contêiner do COI, e o fiz com uma aula estática. O truque está injetando o contêiner na classe estática.

É complicado em um ambiente da web, pois o contêiner pode ser diferente para cada solicitação, enquanto em um aplicativo que não é da Web, provavelmente será o mesmo o tempo todo. No começo, tentei injetar a direção do contêiner com um método, mas isso rapidamente falhou na próxima solicitação da web! Então eu inventei isso:

public static class IoCContainer
{
    public static void SetServiceLocator(Func<IServiceLocator> getLocator)
    {
        m_GetLocator = getLocator;
    }
    static private Func<IServiceLocator> m_GetLocator = null;

    public static T GetInstance<T>(string typeName)
    {
        return m_GetLocator().GetInstance<T>(typeName);
    }
}

Agora no meu global.asax.cs eu faço isso:

protected void Application_Start(object sender, EventArgs e)
{
    var builder = new Autofac.Builder.ContainerBuilder();
    ... register stuff ...
    var container = builder.Build();
    _containerProvider = new Autofac.Integration.Web.ContainerProvider(container);
    Xyz.Core.IoCContainer.SetServiceLocator(() => 
        new AutofacContrib.CommonServiceLocator.AutofacServiceLocator
            (_containerProvider.RequestContainer));
}
public IContainerProvider ContainerProvider
{
    get { return _containerProvider; }
}
static IContainerProvider _containerProvider;

E as chamadas para resolver as dependências se parecem

var someService = Xyz.Core.GetInstance<ISomeService>();

Então, em vez de passar por um contêiner específico, passe um delegado que sabe como obter um contêiner. Para aplicativos que não são da Web, o delegado provavelmente retornaria apenas o que o construtor.build () serve.

Minha pergunta aos especialistas é: isso faz sentido? Eu tenho uma maneira fácil de chegar a algo que pode resolver dependências sem saber qual é o produto do contêiner ou de onde vem o próprio contêiner. O que você acha?

Foi útil?

Solução

Usamos um padrão semelhante principalmente devido ao fato de o COI ter sido introduzido em uma arquitetura não-DI. Assim, a necessidade de poder chamar explicitamente o contêiner para obter serviços, que basicamente é o padrão de fábrica.

O verdadeiro benefício do COI é alcançado quando todas as dependências podem ser injetadas e seu código não tem mais dependência do localizador de serviços. Autofac.integration.web possui manipuladores que executarão injeção em seus objetos de página que tornarão o localizador de serviço estático obsoleto. Na IMO, essa é a maneira preferida, no entanto (como no nosso caso), o localizador de serviço nem sempre pode ser evitado.

Dito isto, como você já isolou seu aplicativo do contêiner usando a classe ioccontainer, não vejo razão para ter a abstração adicional do AutofacServicelocator dentro do ioccontainer. Resumindo a linha de baixo é que o ioccontainer já é o seu localizador de serviço e deve ser "permitido" acesso direto à implementação do contêiner.

Aqui está a minha opinião na aula do seu localizador de serviço:

public static class IoCContainer
{
    private static IContext GetContainer()
    {
        var cpa = 
             (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
        return cpa.ContainerProvider.RequestContainer;
    }

    public static T GetInstance<T>()
    {
        return GetContainer().Resolve<T>();
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top