2016-08-08 1 views
-1

마침내 IoC 및 기타 패턴을 학습하는 과정을 밟았으며 어셈블리 목록을 기반으로 개방형 제네릭을 등록하려고 할 때 문제가 발생했습니다. 별도의 클래스 라이브러리에 프레임 워크의 핵심을 구축하고 프레임 워크에서 상속하는 테스트 클래스를 선언하는 일련의 테스트 프로젝트가 있습니다.간단한 인젝터 및 어셈블리 스캐닝

문제는 그 ICommandHandler<> 개방 일반적인 아무것도 찾을 실패 있도록 AddPersonCommandHandler : ICommandHandler<AddPersonCommand> 런타임에로드되지 않으며 framework.test.service DLL을. 사전에 AddPersonCommandHandler 인스턴스를 만들어야합니다. 그런 다음 목록에 추가 어셈블리가 하나만 있으면 작동합니다.

로드를 강제하는 간단한 방법이 있습니까?

=========== 편집 : 이것은 앱 도메인과 다른 어셈블리에 대한 참조를 보유하고있는 단위 테스트 프로젝트의 와이어 업 코드입니다.

public Container SetupIoc() 
{ 
    var container = new Container(); 

    container.Register(typeof(IUnitOfWork), typeof(EntityFrameworkUnitOfWork), Lifestyle.Singleton); 

    var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 

    container.Register(typeof(ICommandHandler<>), assemblies); 


    container.Verify(); 

    return container; 
} 

IUnitOfWork

는 Database.Interface.dll 에 ICommandHandler<>는 Test.Service.dll에 Core.dll AddPersonCommandHandler에 - 함께 진정한 해결책을 넣어 흉내 프로젝트 설정까지 구조의 스위트의 일부 및 참조 단위 테스트.

그래서, UnitOfWork을 직접 지정했기 때문에 단위 또는 작업 등록이 올바르게 작동합니다. 반면에 ICommandHandler 인터페이스는 성공적으로 바인딩하는 코어에 있습니다. 게시 확인() 작업 단위 등록은 container에만 표시됩니다. Test.Service.dll을로드하려면 AddPersonCommandHandler이 나타나고 TestInit 메서드에서 AddPersonCommand을 인스턴스화 할 수 있습니다.

프로젝트의 모든 dll을 수동으로로드해야하는 경우가 조금 있습니다. 그리고 DLL에 대한 실행 폴더를 스캔하면 일부는 이미로드 된 상태입니다 ... 다시로드가 잘 수행 될지, 이미로드되어 있는지 알아보기 위해 신중한 검사가 필요합니까?

+2

사용 된 프레임 워크에 따라 유형을 명시 적으로 등록 /로드 할 수있는 텍스트 기반 구성이 가능하거나 'Assembly.Load()'를 사용하여 수동으로 수행 할 수 있습니다 (어셈블리 참조를 추가해도 런타임에로드되지 않습니다)). 지금 당장 나는이 질문을 완전히 이해할 수 있을지 확신하지 못한다. – Lucero

+0

나는 다른 해결책을 보았으므로 연구를 수행했다.내가 알고 싶었던 것은 어셈블리를 직접 스캔해야만로드 할 수있는 유일한 방법이었습니다. –

+0

등록 코드를 사용하여 어떤 플랫폼이 사용되었는지, mvc, wpf, windows 서비스 등을 알려주십시오. –

답변

2

어셈블리가로드되었는지 확인하려면 AddPersonCommandHandler 인스턴스를 명시 적으로 만들 필요가 없습니다. AppDomain.CurrentDomain.GetAssemblies()을 호출하기 전에 코드에서 정적으로 참조하는 어셈블리의 형식 (예 : AddPersonCommandHandler)을 참조하기 만하면됩니다. 예 :

// Load BL assembly 
Type type = typeof(AddPersonCommandHandler); 

container.Register(typeof(ICommandHandler<>), AppDomain.CurrentDomain.GetAssemblies()); 

가장 좋은 것은이 참조를 구성 루트에 보관하는 것입니다. 이렇게하면 컨테이너가 초기화 된 위치 (App_start 또는 통합 테스트)와 상관없이 같은 어셈블리가로드됩니다. 이 유용한 유형을 포함하지 어셈블리의 대량 스캔을 방지하기 때문에,

// Adding the (redundant) namespace of the type makes it very clear to the 
// user if this type is still located in the business layer. 
Assembly[] businessLayerAssemblies = new[] { 
    typeof(MyComp.MyApp.BusinessLayer.AddPersonCommandHandler).Assembly 
} 

container.Register(typeof(ICommandHandler<>), businessLayerAssemblies); 
container.Register(typeof(IQueryHandler<,>), businessLayerAssemblies); 
container.Register(typeof(IEventHandler<>), businessLayerAssemblies); 
container.Register(typeof(IValidator<>), businessLayerAssemblies); 

나는 후자의 접근 방식을 선호 :

더 명시 적 방법은 등록에 사용되어야한다 어셈블리의 명시 적 목록을 만드는 것입니다 (어셈블리를로드하는 형식을 암시 적으로 참조하는 대신) 어셈블리에 대해 매우 명시 적입니다.

+0

멋진 친구. 그것이 작동하는 동안 차라리 그렇게 할 필요가 없다는 것이 단순한 접근이라고 생각합니다. 시간 내 주셔서 감사합니다. –

+0

@StephenYork 또는 [this] (https://stackoverflow.com/a/12781486/264697)을 수행 할 수도 있습니다. – Steven

+0

그래, 나는 그것을 회피하고 당신이 원한 답장에서 옵션 B를 사랑하기를 바랐다. 다시 한번 감사드립니다. –