2016-07-12 1 views
0

컨트롤러에 서비스를 주입하려고하지만 여러 매개 변수에 따라 다른 서비스 인스턴스를 주입하려고합니다. 사실이 부분에 대해서는 작동하고 있습니다.ASP.NET 핵심 종속성 주입 : Func 대리인을 사용하여 런타임에 서비스가 해결됨

내가 원하는 것은 구성 파일에서 얻은 일부 구성을 기반으로 DRY 규칙을 존중하며 (반복하지 않음) IRepository<Database>의 특정 인스턴스를로드하는 것입니다.

public abstract class FooServicesProvider 
{ 
    public Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider => 
    { 
     return null; 
    }; 
} 

public class FooFileSystemServicesProvider : FooServicesProvider 
{ 
    public new Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider => 
    { 
     //Specific code determining which database to use and create a new one if needed 
     //our databases are FOLDERS containing some files 
     //knowing how chosenDb.FullName is set is not important here 
     //[...] 
     var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName); 
     databaseRepository.testProperty = "Foo value"; 
     return databaseRepository; 
    }; 
} 

공지 사항 내 Func을의 코드를 다시 정의하는 데 사용되는 새로운 키워드 :

나는이 2 개 개의 클래스가 있습니다. 이것은 Func 대리자 때문에 발견 된 가장 좋은 방법입니다. 매우 제한적입니다. 인터페이스에서 사용할 수 없으므로 무시할 수도 없습니다. Startup.csConfigureServices에서 지금

방법이 코드를 가지고 내 문제가 새로운 키워드가 런타임에 무시하고 실행 Func을가에 선언 된 하나입니다이다

var fakeConfiguration = "File"; 
FooServicesProvider servicesProvider = null; 
if(fakeConfiguration == "File") 
{ 
    servicesProvider = new FooFileSystemServicesProvider(); 
} 
else 
{ 
    servicesProvider = new AnotherFooServicesProvider(); 
} 
//Here is the tricky part 
//This should call FooFileSystemServicesProvider.DatabaseRepository because of the "new" keyword, but it's NOT 
services.AddScoped<IRepository<Database>>(servicesProvider.DatabaseRepository); 

파생 된 클래스 대신 기본 클래스.

services.AddScoped<IRepository<Database>>((servicesProvider as FooFileSystemServicesProvider).DatabaseRepository); 

을 일하고 나는이 작업을 수행하지만 내가있는 마지막이 될 것입니다 내 servicesProvider을 입력 알 수 없습니다로 캐스팅하지 않으려면.

서비스 제공자의 유형을 가져 와서 자체 형식으로 변환하려고 시도했지만 형식 변수와 클래스가 다르므로 컴파일러 오류가 발생합니다.

그렇다면 어떻게하면 런타임에 좋은 Func을 실행할 수 있습니까? 나는 마침내 내가 원하는 것을 할 관리 있도록

+0

기본 클래스'virtual'의'DatabaseRepository'를 만들고 파생 된 타입에서'override'를 사용해야합니다. – Steven

+0

대리자 속성 선언에서 override로 새 키워드를 대체하십시오. 작동합니까 ? –

+0

물론'new'는 기본 클래스의 메소드/속성을 숨기고 대체하거나 무시하지 않기 때문에'new' 키워드는 무시됩니다 ... – Tseng

답변

1

좋아 감사합니다, 그것은 내 주요 문제는 내 Func을이 방법하지만 대리인이 아니었다는 사실을 처리 할 수 ​​있었다, 어려운 사실이 아니었다. 나는이 변수 유형을 다루는 데 익숙하지 않다.

Startup.cs에 내 코드가 변경되지 그러나 여기

public abstract class FooServicesProvider 
{ 
    public Func<IServiceProvider, IRepository<Database>> DatabaseRepository { get; protected set; } 
} 

public class FooFileSystemServicesProvider : FooServicesProvider 
{ 
    public FooFileSystemServicesProvider() 
    { 
     base.DatabaseRepository = GetDatabaseRepository; 
    } 

    private DatabaseFileSystemRepository GetDatabaseRepository(IServiceProvider serviceProvider) 
    { 
     //Specific code determining which database to use and create a new one if needed 
     //our databases are FOLDERS containing some files 
     //knowing how chosenDb.FullName is set is not important here 
     //[...] 
     var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName); 
     databaseRepository.testProperty = "Foo value"; 
     return databaseRepository; 
    }   
} 

이런 경우 사람들에 내 사용자 지정 ServicesProvider의 새로운 코드가 궁금하다

: DatabaseFileSystemRepository이 인터페이스를 구현하는 클래스입니다 IRepository<Database>>

하는 경우 누구나 다른 해결책을 생각해냅니다. 나는 그것을 알고 싶어합니다.