2017-11-13 3 views
1

DbContext 구현을위한 연결 문자열이 여러 개인 응용 프로그램이 있습니다. 이를 소비 클래스에서 지원하기 위해 DbContext 인스턴스를 제공 할 수있는 Get 메서드를 사용하여 IDbContextProvider 인터페이스를 만들었습니다.간단한 인젝터 꾸미 꾸기 및 공분산

나는 또한 ICommandHandler 일을 처리했습니다. 성공적인 명령 실행시 DbContext.SaveChangesAsync()을 호출 할 데코레이터를 만들려고합니다. 나는이 같은 내 장식 등록 해요 : 나는 DbContext implementaiton에 대한 형식 매개 변수를 추가하지 않기 때문에, 지금

container.RegisterDecorator(typeof(ICommandHandler<>), 
    typeof(SaveChangesCommandHandlerDecorator<>)); 

을, 나는 DbContext에서 파생 된 모든 클래스가 SaveChangesAsync() 방법을 알고, 내가 상상 공분산을 사용할 수 있습니다. 그래서 내 인터페이스는 다음과 같습니다

public public interface IDbContextProvider<out TDbContext> where TDbContext : DbContext 
{ 
    TDbContext Get(DbPrivileges privileges); 
} 

그리고 내 장식의 관련 부분 : 그러나

public class SaveChangesCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand> 
    where TCommand : ICommand 
{ 
    private readonly ICommandHandler<TCommand> _handler; 
    private readonly IDbContextProvider<DbContext> _dbContextProvider; 

    public SaveChangesCommandHandlerDecorator(
     ICommandHandler<TCommand> handler, IDbContextProvider<DbContext> dbContextProvider) 
    { 
     _handler = handler; 
     _dbContextProvider = dbContextProvider; 
    } 

    ... 

, 내 용기에 Verify() 전화, 그것이 찾고으로 IDbContextProvider이 잘못되었다고 불평 "기본"IDbContextProvider<DbContext> 대신 내 애플 리케이션에 등록 된 것들 중 하나.

타입 SaveChangesCommandHandlerDecorator의 생성자 <는 CreateUserCommand> 'dbContextProvider'이름의 파라미터를 포함하고 SaveChangesCommandHandlerDecorator < CreateUserCommand의 생성자> IDbContextProvider < DbContext 보장 registered.Please 등록 또는 변경되지 않았는지> < DbContext를 IDbContextProvider 입력 >. 요청 된 형식이 (Redacted) .IDbContextProvider < Microsoft.EntityFrameworkCore.DbContext> 인 동안 다른 형식 (Redacted) .IDbContextProvider < TDbContext>에 대한 등록이 있음에 유의하십시오.

Simple Injector는 dbContextProvider 매개 변수에 주입 할 구체적인 유형을 알 수 없으므로 실제로 의미가 있습니다.

기본 장식물 인 ICommandHandler 구현의 종속성을 들여다 볼 수 있도록 내 장식자를 만드는 방식을 사용자 정의하는 방법이 있습니까? 생성시 여기에서 IDbContextProvider 서명을 선택하십시오. 그래서 만약 내 명령 처리기가 IDbContextProvider<AwesomeDbContext>이라면, 나는 그것을 내 데코레이터를 위해서도 해결하기를 원한다.

답변

2

그래서 내가 정리해 볼께 : 응용 프로그램은 다음과 같은 여러 DbContext implemtantations 포함 :

  • AwesomeDbContext을
  • EventBetterDbContext
  • BrilliantDbContext

이제 각 명령 핸들러는 일반적으로에 따라 달라집니다 하나의 특정 DbContext 구현, IDbContextProvider<TDbContext> 점점함으로써 TDbContext은 특정 DbContext 구현입니다.

데코레이터 명령 핸들러가 무엇을 원 하느냐에 따라 정확히 동일한 IDbContextProvider<TDbContext> 구현을 데코레이터에 삽입하려고하므로 특정 인스턴스에 대한 변경 사항을 저장할 수 있습니다.

귀하의 질문을 정확하게 요약하면 귀하의 질문에 대한 짧은 대답은 : 아니오, 귀하는 그렇게 할 수 없습니다. 더 이상 대답은

는, 그래이 당신의 SaveChangesCommandHandlerDecorator<TCommand, TDbContext> 장식에 TDbContext에 대한 별도의 제네릭 형식 인수를 추가하여 실제로 가능하고, Func<DecoratorPredicateContext, Type> 허용하는 RegisterDecorator 오버로드를 사용합니다. 제공된 DecoratorPredicateContext을 팩토리 델리게이트를 사용하여 Expression 속성을 분석하여 IDbContextProvider<TDbContext>이 주입되었는지 확인하고 해당 정보를 기반으로 SaveChangesCommandHandlerDecorator<TCommand, TDbContext> 부분 완료 버전을 작성하고 TDbContext을 채우지 만 Simple Injector는 TCommand으로 남겨 둡니다. 기입하십시오.

하지만 솔직히 말해서, 나는이 길을 택하지 않을 것입니다. 많은 작업이 필요하고 코드를 이해하기가 어려우며 동료가 당신을 싫어하게됩니다.

대신 IDbContextProvider<TDbContext> 인스턴스 목록을 데코레이터에 삽입 해보십시오. IDbContextProvider<out TDbContext> 등록을 별도로 수행하거나 RegisterCollection을 사용하여 컬렉션의 일부로 등록 할 수 있습니다.

컬렉션을 삽입하면 데코레이터는 모든 DbContext 인스턴스에서 변경 사항 저장을 호출 할 수 있습니다. SaveChanges은 변경 사항이 없을 때 정말 빠를 것입니다. 따라서 성능 측면에서 걱정할 것이 없습니다.

+0

그래, 이건 내 질문을 올바르게 요약하고 상세한 답변을 주셔서 감사합니다! 나는 수집 경로를 고려하지 않았지만 확실히 더 깨끗한 코드를 생성 할 것입니다. –

관련 문제