Nancy: Não é possível usar o padrão IOptions com Nancy / TinyIoc

Criado em 25 jan. 2016  ·  6Comentários  ·  Fonte: NancyFx/Nancy

Estou tentando implementar o padrão de opções (conforme recomendado aqui: https://docs.asp.net/en/latest/fundamentals/configuration.html#options-config-objects) em um projeto com NancyFX / TinyIOC, mas não é trabalhando.

Estou registrando as opções no método Startup.cs / ConfigureServices, mas quando tento injetar as configurações na minha classe, TinyIoc lança Nancy.TinyIoc.TinyIoCResolutionException: Não foi possível resolver o tipo: AppSettings.

Acho que isso ocorre porque o padrão de opções usa Microsoft.Extensions.DependencyInjection, mas Nancy usa TinyIoc como padrão, então TinyIoc tenta resolver IOptions e falha.

Existe uma maneira de usar IOptions <> com TinyIoc?

Na pior das hipóteses, posso substituir o TinyIoc pelo MS DependencyInjection?

Este é o meu código:

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();
    services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
}

MyService.cs:

public SearchService(IOptions<AppSettings> config)
{
}

Erro:

Application startup exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Something went wrong when trying to satisfy one of the dependencies during composition, make sure that you've registered all new dependencies in the container and inspect the innerexception for more details. ---> Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type: Nancy.NancyEngine ---> Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type: Nancy.Routing.DefaultRequestDispatcher ---> Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type: Nancy.Routing.DefaultRouteResolver ---> Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type: Nancy.Routing.RouteCache ---> Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type: MyProject.MyService ---> Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type: Microsoft.Extensions.OptionsModel.IOptions 1 [[MyProject.AppSettings, MyProject, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]] ``

Algumas informações extras:

"dependencies": {
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.Owin": "1.0.0-rc1-final",
    "Nancy": "1.4.3",
    "Microsoft.Framework.ConfigurationModel": "1.0.0-beta4",
    "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
    "Microsoft.Extensions.OptionsModel": "1.0.0-rc1-final"
},

Versão de tempo de execução DNX:

1.0.0-rc1-update1 mono

Muito obrigado.

Comentários muito úteis

@RTodorov Pode ser apropriado criar uma biblioteca bootstrapper do Nancy que usa Microsoft.Extensions.DependencyInjection como o contêiner no lugar do TinyIoC; isso já é feito para muitos contêineres diferentes.

Todos 6 comentários

Você não está registrando IOptionsno contêiner de Nancy em qualquer lugar, então não vai funcionar, não tenho certeza de que "serviços mágicos".(Configuration.GetSection ("AppSettings")); "está funcionando nos bastidores, mas você precisará registrar esse tipo no contêiner de Nancy:

  • Criando seu próprio bootstrapper, passando IOptionsem seu ctor, usando aquele bootstrapper onde você está configurando o uso de Nancy, então no bootstrapper registre isso em ConfigureApplicationContainer
  • Se houver mais tipos que você deseja compartilhar, faça o mesmo que o anterior, mas em vez de passar os tipos, passe um TinyIocContainer recém-configurado e retorne essa instância para GetApplicationContainer em seu bootstrapper derivado.

Espero que isso faça sentido.

Tentei me registrar fazendo o seguinte:

Nancy.TinyIoc.TinyIoCContainer.Current.Register(typeof(IOptions<>), typeof(OptionsManager<>));

Qual BTW é o que services.AddOptions(); faz por baixo do capô para Microsoft.Extensions.DependencyInjection

É isto que você quer dizer?

services.Configure () pegará a configuração carregada e se registrará no MS DI para quando alguém solicitar AppSettings.

Eu adicionei isso no bootstrap personalizado:

container.Register<IOptions<ElasticSearchConfig>, OptionsManager<ElasticSearchConfig>>();

e agora o erro não acontece mais, mas infelizmente o objeto é criado vazio.

Ao depurar, percebi que isso retornará o objeto preenchido correto:

`var appSettings = app.ApplicationServices.GetService> (); ``

Mas isso retornará um objeto vazio:

var appSettings = Nancy.TinyIoc.TinyIoCContainer.Current.Resolve<IOptions<AppSettings>>();

Ainda assim, TinyIoc está tomando o lugar de Ms Framework DI quando eu solicito IOptions. Também percebi que todas as Microsoft. * Dlls estão na lista de Ignorar do TinyIoc. Isso significa que ele não deve "responder" quando eu pedir Microsoft.Extensions.OptionsModel.IOptions ?

Como eu disse originalmente, você precisa passar essa instância de tipo, ou um contêiner configurado, não adianta apenas registrar o próprio tipo, pois ele precisa ser construído pela fábrica GetService.

Ei, agora entendi o que você disse, funcionou! Enviei IApplicationBuilder para o bootstrap customizado e de lá registrei o IOptions<AppSettings> com o valor retornado de ApplicationServices.GetService() .

Não tenho certeza se esta é a melhor solução, pois o TinyIoc funcionará como um gateway entre meu serviço e Microsoft.Extensions.DependencyInjection .

@RTodorov Pode ser apropriado criar uma biblioteca bootstrapper do Nancy que usa Microsoft.Extensions.DependencyInjection como o contêiner no lugar do TinyIoC; isso já é feito para muitos contêineres diferentes.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

jlennox picture jlennox  ·  5Comentários

juniormayhe picture juniormayhe  ·  4Comentários

bsommardahl picture bsommardahl  ·  3Comentários

phillip-haydon picture phillip-haydon  ·  3Comentários

Radzhab picture Radzhab  ·  11Comentários