2017-11-23 12 views
-1

클래스 라이브러리에 클래스를 설정하고 Startup.cs의 서비스에서이를 주입 가능하도록 설정하여 문제없이 작동하도록했습니다. 예상했다. 내가하고 있어요 테스트 응용 프로그램에서 클래스 라이브러리 프로젝트에 주입 가능한 Asp.Net Core 2.0의 Configuration 객체

. 나는

// *If* you need access to generic IConfiguration this is **required** 
     services.AddSingleton<IConfiguration>(Configuration); 

     services.AddOptions(); 
     // Add our class objects so they can be injected 

services.Configure<TestAppServices.ConfigurationClasses.ApplicationSettings>(Configuration.GetSection("ApplicationSettings")); 
     services.Configure<TestAppServices.ConfigurationClasses.LoggingSettings>(Configuration.GetSection("Logging")); 
     services.Configure<TestAppServices.ConfigurationClasses.ApplicationIconUrlSettings>(Configuration.GetSection("ApplicationIconUrls")); 
     services.Configure<TestAppServices.ConfigurationClasses.DatabaseConfigurationSettings>(Configuration.GetSection("ConnectionStrings")); 
     services.Configure<TestAppServices.ConfigurationClasses.SmsSettings>(Configuration.GetSection("SmsSettings")); 
Startup.cs

에서 데이터 클래스 라이브러리 프로젝트 플러스 내 MVC 응용 프로그램 프로젝트 (코어 2.0.1 EF 2.0.1 MVC6)가

설정 한 개별 클래스의 모든 설정에 액세스 할 수 있지만 다음은 작동하지 않습니다.

private static IConfiguration _configuration { get; set; } 
    private const string AppSettingsConnectionsHeader = "ConnectionStrings"; 

    public DatabaseHelpers(IConfiguration configuration) 
    { 
     _configuration = configuration; 
    } 

    public static ConnectionStrings GetConnections() 
    { 
     var cs = new ConnectionStrings(); 
     _configuration.GetSection(AppSettingsConnectionsHeader).Bind(cs); 
     return cs; 
    } 

나는 일반적인 오류를 얻고있다

System.NullReferenceException : 개체 참조가 개체의 인스턴스로 설정되지 않았습니다.

_configuration이 null이므로 주입되지 않습니다.

GetConnections 방법

은 클래스 라이브러리 프로젝트의 주 사용하므로 실제 구성 객체를 설정하는 특별한 방법이 있나요 그래서

var cs = DatabaseHelpers.GetConnections(); 

같은 컨트롤러에서 호출되는?

업데이트 : 나는 다음과 같은

public static class ConnectionStrings 
{ 
    public static string DefaultConnection => "DefaultConnection"; 
    public static string TestingConnection => "TestingConnection"; 
    public static string StagingConnection => "StagingConnection"; 
    public static string ProductionConnection => "ProductionConnection"; 
    public static string DevelopmentConnection => "DevelopmentConnection";  
} 

public class ConfigurationSettings 
{ 
    private readonly IConfiguration _configuration; 

    public ConfigurationSettings(IConfiguration config) 
    { 
     _configuration = config; 
    } 

    public DatabaseConfigurationSettings GetConnectionStringFor(DatabaseIsFor dbfor) 
    { 
     var dbcs = new DatabaseConfigurationSettings(); 
     switch (dbfor) 
     { 
      case DatabaseIsFor.Development: 
       if (!string.IsNullOrEmpty(_configuration.GetConnectionString(ConnectionStrings.DevelopmentConnection))) 
       { 
        dbcs.CompleteConnectionString = _configuration.GetConnectionString(ConnectionStrings.DevelopmentConnection); 
        dbcs.ConnectionName = ConnectionStrings.DevelopmentConnection; //== _connections.Value.DevelopmentConnection.ToString(); 
        return dbcs; 
       } 
       break; 

      case DatabaseIsFor.Testing: 
       if (!string.IsNullOrEmpty(_configuration.GetConnectionString(ConnectionStrings.TestingConnection))) 
       { 
        dbcs.CompleteConnectionString = _configuration.GetConnectionString(ConnectionStrings.TestingConnection); 
        dbcs.ConnectionName = ConnectionStrings.TestingConnection; //== _connections.Value.TestingConnection.ToString(); 
        return dbcs; 
       } 
       break; 

      case DatabaseIsFor.Staging: 
       if (!string.IsNullOrEmpty(_configuration.GetConnectionString(ConnectionStrings.StagingConnection))) 
       { 
        dbcs.CompleteConnectionString = _configuration.GetConnectionString(ConnectionStrings.StagingConnection); 
        dbcs.ConnectionName = ConnectionStrings.StagingConnection; //== _connections.Value.TestingConnection.ToString(); 
        return dbcs; 
       } 
       break; 

      case DatabaseIsFor.Production: 
       if (!string.IsNullOrEmpty(_configuration.GetConnectionString(ConnectionStrings.ProductionConnection))) 
       { 
        dbcs.CompleteConnectionString = _configuration.GetConnectionString(ConnectionStrings.ProductionConnection); 
        dbcs.ConnectionName = ConnectionStrings.ProductionConnection; //== _connections.Value.TestingConnection.ToString(); 
        return dbcs; 
       } 
       break; 

     } 
     dbcs.CompleteConnectionString = _configuration.GetConnectionString(ConnectionStrings.DefaultConnection); 
     dbcs.ConnectionName = ConnectionStrings.DefaultConnection; //== _connections.Value.DefaultConnection.ToString(); 
     return dbcs; 
    } 
} 

그리고

public class HomeController : Controller 
{ 
    private IConfiguration Configuration { get; set; } 

    public HomeController(IConfiguration configuration) 
    { 
     Configuration = configuration; 
    } 

    public IActionResult Index() 
    { 
     // test view to check that this works 
     var cs = new ConfigurationSettings(Configuration);    
     var dbcs = cs.GetConnectionStringFor(DatabaseIsFor.Production); 

     var svm = SettingsViewModel(dbcs); 
     return View(svm); 
    } 
} 

그리고 작동을 다음과 같이 내가 컨트롤러에서 사용 내 클래스 라이브러리 프로젝트를 재구성 serpent5의 대답은 당

완벽하게 괜찮습니다, 을 제외하고 나는 왜 내가 파해야했는지 이해하지 못합니다. ss ConfigurationSettings를 새로 만들 때의 구성. Startup.cs ConfigureServices에 추가 한 이후로 이미 해당 버전을 사용할 수 있습니까?

// Access to generic IConfiguration 
services.AddSingleton(Configuration); 
+0

생성자에 중단 점을 넣습니다. 맞았나요? –

+0

@ serpent5 ... 위대한 호출, 생성자의 중단 점이 충돌하지 않습니다, 왜? – dinotom

+0

@ serpent5 ... 주사 구문이 잘못 되었나요? 어떻게 든 IOptions를 구성 루트에 사용합니까 아니면 구성에서 클래스 설정을위한 IOptions입니까? – dinotom

답변

2

클래스의 인스턴스를 인스턴스화하지 않으려면 Constructor Injection을 사용할 수 없습니다. 귀하가 제공 한 코드에서 DatabaseHelpers의 인스턴스가 생성자를 통해 IConfiguration으로 주입되도록 설정했지만 클래스 자체는 Dependency Injection에 참여하지 않으므로 해당 생성자를 호출 할 필요가 없습니다.

특정 예제에 대한 한 가지 해결 방법은 명시 적으로 정적 클래스를 어떤 식 으로든 초기화하는 것입니다. 이 같은 DatabaseHelpers에 무언가를하는 새로운 방법을 추가 할 수 있습니다 : 당신은 그럼 그냥 응용 프로그램을 시작할 때 어딘가에서이 설정 것

public static Initialize(IConfiguration configuration) 
{ 
    _configuration = configuration; 
} 

- 아마 ConfigureServices에. 예 ::

services.AddSingleton<IConfiguration>(Configuration); 
DatabaseHelpers.Initialize(Configuration); 

이 문제는 기술적 인 해결 방법이지만 정적 헬퍼를 사용하는 것이 가장 좋은 방법인지 여부를 고려해 보는 것이 좋습니다. 나는 실제 구현이 DatabaseHelpers이라고 가정하고 여기에 표시된 것보다 더 복잡하며 자신의 Dependency Injection 서비스 콜렉션에 ConnectionStrings의 인스턴스를 추가하고 대신 사용할 수는 없다고 가정합니다.

업데이트 : 종속성 주입은 실제로 마술이 아니며 단지 pattern입니다. 클래스를 생성하는 책임을 다른 엔티티 (일반적으로 MVC 세계에서 컨트롤러 활성화 프로세스 임)에 위임 할 때 잘 작동하지만 생성을 직접 제어 할 때는 작동하지 않습니다. 업데이트 된 예에서는 ConfigurationSettings 생성에 대한 전적인 책임을 져야합니다. 따라서 생성자 인수를 제공해야합니다.

직접 처리하고 싶지 않은 경우 ConfigurationSettings을 서비스 컬렉션에 추가하고 DI 컨테이너에서 종속 형 Configuration을 해결할 수 있습니다.

+0

@ serpent5 ... upvoted ...이 질문과 관련된 추가 질문은 내 게시물 업데이트를 참조하십시오. – dinotom