2016-12-13 1 views
0

저는 Autofac과 ASP.NET Core의 비교적 새로운 사용자입니다. 저는 최근에 '클래식'ASP.NET WebAPI 프로젝트에서 ASP.NET 코어로 작은 프로젝트를 이식했습니다. Autofac에 문제가 있습니다. 특히 제네릭 유형을 등록하는 것이 좋습니다. Autofac 같이 (부분적으로) 구성된다ASP.NET 코어에서 Autofac으로 제네릭 유형을 등록 할 때 문제가 발생했습니다.

readonly private ICommandHandler<UpdateCustomerCommand> _updateCustomerCommand; 
public ValuesController(ICommandHandler<UpdateCustomerCommand> updateCustomerCommand) 
{ 
    _updateCustomerCommand = updateCustomerCommand; 
} 

:

이 프로젝트는 각 명령어 핸들러는

public class UpdateCustomerCommandHandler: ICommandHandler<UpdateCustomerCommand> 

이러한 명령어 핸들러

같은 컨트롤러에 주입 같은 폐쇄 총칭, 명령 패턴을 사용 :

var builder = new ContainerBuilder(); 
var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 
//This doesn't seem to be working as expected. 
builder.RegisterAssemblyTypes(assemblies) 
    .As(t => t.GetInterfaces() 
     .Where(a => a.IsClosedTypeOf(typeof(ICommandHandler<>))) 
     .Select(a => new KeyedService("commandHandler", a))); 

위의 내용은 t 그는 예상대로 일반. 등록을 위해 아래의 방법을 사용하면 잘 작동합니다. 'BusinessLogic.ICommandHandler`1 [BusinessLogic 유형의 서비스를 확인할 수 없습니다 :

builder.RegisterType<UpdateCustomerCommandHandler>().As<ICommandHandler<UpdateCustomerCommand>>(); 

나는 "그것은 작동하지 않습니다"라고

는, 내 말은 컨트롤러의 인스턴스를 시도 할 때, 나는 "InvalidOperationException이를 얻을 수 있다는 것입니다. UpdateCustomerCommand] '를 실행하는 동안'AutoFac_Test.Controllers.ValuesController '

이 기능은이 프로젝트의 Full WebAPI 버전에서 잘 작동하지만 ASP.NET Core에서 다시 제작 한 후에는 작동하지 않습니다. 분명한 것은 ASP.NET 코어로 포팅하기 전에 완벽하게 작동하는 것입니다. 여기

내가이 문제를 다시 사용했던 코드에 대한 링크입니다 : https://dl.dropboxusercontent.com/u/185950/AutoFac_Test.zip

**** 발견 해결 AFTER 편집 ****

잘못된 사실 아무것도 없었다 내 Autofac 구성 및 Autofac 자체가 아닙니다. 무슨 일이 있었는지, 어셈블리를 스캔하기 위해 내 종속 어셈블리의 결과를 바꿨다는 것입니다. (AppDomain.CurrentDomain.GetAssemblies()을 더 우아하게 바꾸었지만 API 어셈블리의 종속성을 새 어셈블리를 참조하도록 수정하지 않았습니다.) 그래서 Autofac은 무슨 일이 있었 올바르게로드 어셈블리는

+0

가능한 복제 내가 할 수있다 -

  • 당신이 decorators 사용하는 경우, 길을 등록 작업이 당신은 장식이 으로 적용 할 수있는 서비스를 정의 오픈 Generic의 유형에 따라 AutoFac에 키 서비스를 제공하십시오. "(http://stackoverflow.com/questions/13636492/can-i-make-a-keyed-service-for-autofac-based-on-the- open-generic) – Tseng

  • +0

    제안에 감사드립니다. 그러나이 질문은 그와 중복되지 않습니다. 이 경우 요청자는 특정 기반에서 일반 파생을 등록하고 특정 폐쇄 일반 인터페이스를 구현하려고했습니다. 내 경우에는 특정 폐쇄 된 일반 인터페이스의 구현을 등록하려고합니다. 게다가, 위의 구문은 고전적인 ASP.NET에서는 꽤 잘 작동하지만 ASP.NET 코어에서는 제대로 작동하지 않는 것으로 입증되었습니다. 이 문제를 일으킬 수있는 리플렉션이 변경된 것인지 궁금합니다. – QuietSeditionist

    답변

    0

    Autofac가 내장되어 지원 오픈 제네릭의 폐쇄 유형을 등록 할 ... 인터페이스와 내가 기대 구현을 포함하지 않은 이전 버전 일 수 있습니다.

    builder 
        .RegisterAssemblyTypes(ThisAssembly) 
        .AsClosedTypesOf(typeof(ICommandHandler<>)); 
    

    이것은 조립품을 스캔하고 개방형 일반 ICommandHandler<> 인터페이스를 닫는 유형을 찾아 각각에 대해 등록합니다 귀하의 사례에서 구현 한 폐쇄 된 일반 인터페이스 (ICommandHandler<UpdateCustomerCommand>).

    예를 들어 작동하지 않는 것은 서비스에 키를 연결한다는 것입니다. ValuesController을 인스턴스화 할 때 Autofac이 ICommandHandler<UpdateCustomerCommand>의 키가있는 버전을 찾지 않아 예외가 발생합니다. QuietSeditionist의 발언 후

    편집 :

    나는 키가기본 서비스에 조금 자세히 설명하려고합니다.핸들러를 등록하는 방법은 commandHandler 키를 연결하는 것입니다.

    // container will look for a registration for ICommandHandler<UpdateCustomerCommand> associated with the "commandHandler" key 
    container.ResolveKeyed<ICommandHandler<UpdateCustomerCommand>>("commandHandler"); 
    

    ValuesController의 인스턴스를, Autofac이 ICommandHandler<UpdateCustomerCommand>키가 등록을 보이지 않기 때문에 :

    이 컨테이너가 구축되면, 여기 당신이 그런 핸들러를 해결할 수있는 유일한 방법은 것을 의미 그것은 물어 보지 않았다.

    가 실행 년대 상응하는 코드는 - 당신은 예외를 얻기 위해 그 코드를 직접 실행하려고 할 수 있습니다

    // BOOM! 
    container.Resolve<ICommandHandler<UpdateCustomerCommand>>(); 
    

    당신이 서비스하지 않았기 때문에 두 번째 등록이 작동하는 이유는 : 당신이 당신의 핸들러를 하나씩 등록하지 않기 때문에

    // No key 
    builder 
        .RegisterType<UpdateCustomerCommandHandler>() 
        .As<ICommandHandler<UpdateCustomerCommand>>(); 
    
    // commandHandler key 
    builder 
        .RegisterType<UpdateCustomerCommandHandler>() 
        .Keyed<ICommandHandler<UpdateCustomerCommand>>("commandHandler"); 
    

    는하지만, 여기 그들을 키잉없이 등록하는 방법은 다음과 같습니다

    builder 
        .RegisterAssemblyTypes(ThisAssembly) 
        .AsClosedTypesOf(typeof(ICommandHandler<>)); 
    

    /편집

    I 볼 수 있습니다 이 유용 할 수 있습니다 서비스 키잉 두 가지 시나리오 :

    • 당신은 동일한 인터페이스를 구현하는 여러 종류가 있고 다른 구현을 주입 할 다른 서비스에서. 예를 들어 SqlConnectionDB2Connection을 모두 IDbConnection으로 등록한다고 가정 해 보겠습니다. 그런 다음 두 개의 서비스가 있는데, 하나는 SQL Server를 목표로하고 다른 하나는 DB2입니다. 둘 다 IDbConnection에 의존하는 경우 각 서비스에 올바른 것을 주입하고 싶습니다. 첫 번째 예 [자기 설명

    +0

    사실 Decorator 패턴을 사용하고 있으므로이 키를 지정해야합니다. Autofac은 왜이 핵심 버전을 찾지 않을까요? 죄송 합니다만, 귀하의 답변에는 답변이있는 것 같지 않습니다. – QuietSeditionist

    +0

    Decorator 패턴을 사용 하시겠습니까? 원래의 질문은 당신이 그것을 사용하는 것을 언급하지 않았고 당신이 링크 한 .zip은 데코레이터 등록이나'ICommandHandler'의 데코레이터 구현을 포함하지 않습니다. 기본적으로 Autofac은 * default * 서비스 즉, 명시 적으로 이름이 * * * * keyed * 인 서비스를 해결하려고합니다. 그러한 서비스를 해결하기를 원한다면 명시 적으로해야합니다. –

    +0

    샘플 프로젝트를 만들었을 때 프로젝트의 단순화 된 버전이었습니다. 당신은 그것이 핵심 서비스로 등록 라인을 제거했을 때, 그것은 성공적으로 해결되었다는 것이 맞습니다. 나는 방금 전방에 가서 데코레이터 등록을 추가했으며 예상대로 작동하고 있습니다. 내 프로젝트와 제공된 샘플간에 다른 뭔가가 있어야합니다. 고마워, 나는 다시 만들고 다시 일할거야. – QuietSeditionist

    관련 문제