简体   繁体   中英

How to configure an object and override that configuration

I have the following interfaces and classes:

public interface ILoggingService { ... }
public class LoggingService {
    public LoggingService(ILoggingRepository loggingRepository) { ... }
    ...
}

public interface ILoggingRepository { ... }
public class DatabaseLoggingRepository {
    public DatabaseLoggingRepository(string ConnectionString) { ... }
    ...
}
public class FileLoggingRepository {
    public FileLoggingRepository(string LogFilePath) { ... }
    ...
}

I'm refactoring my software to use Unity IoC framework and am looking for a way to pass the specific configuration to each ILoggingRepository implementation.

I think that the best way would be to change DatabaseLoggingRepository's and FileLoggingRepository's constructors to have no parameters at all and have them configured by some configuration file. However, because of my acceptance tests I would need a easy way to override these settings while running my tests.

Am I on the right track and if I am, which configuration files should I use? Alternative ways are welcome as well.

What we've decided to do is create a class, in your case it would be LoggingConfiguration , and have that passed to the constructo of the repository. If you resolve using Unity it will instantiate this class using Activator , wuthout having to register it. In your tests however, you just greate a new instance of a derived configuration class, providing different values.

Does it makes sense? Should I clarify more?

Update : I've decided to provide some additional clarification. So, you already have two implementations, and now you want each configuration to query for its proper configuration setting.

I would extend the ILoggingRepository 's constructor to look like this:

   public ILoggingRepository(ILoggingConfigurationProvider confProvider);

You can then create one implementation for your normal operation which has two properties:

public LoggingConfigurationProvider : ILoggingConfigurationProvider {
 public LoggingConfigurationProvider() {
   // load both values from configuration file
 }

 public string LogPath { get; set; }
 public string ConnectionString { get; set; }
}

When you instantiate your class via normal IoC operation this will get resolved by the container and you'll configuration options will get loaded from the conf file. When you however want to do Unit tests you:

1) Create a new "Mock" implementation

public class MockLoggingConfigurationProvider : ILoggingConfigurationProvider  {
   public MockLoggingConfigurationProvider() {
      // set both values to a test value
   }

   public string LogPath { get; set; }
   public string ConnectionString { get; set; }
}

Now you can either create the repository using a constructor:

new LoggingRepository(new MockLoggingConfigurationProvider());

or if you want the whole IoC mechanism to be used, you simply (when setting up the container) register this implementation of the interface. Because the unit tests are separate, you don't share the registrations right? So that should give you what you need, the ability to change this settings depending on weather they are being executed as a unit test or not.

In real life, I wouldn't even bother with this, and just create a mock logging repository and have it write somewhere else. Unless you want to test the repository to a test database/file. In which case I'd do as specified.

Hope it helps.

As a design suggestion does not force IoC to deal with configuration stuff. Each logger should manage the configuration the way they prefer in its implementation. IoC should just inject the logger. For the unit/integration test, in both case you should e able to provide a configuration for the logger, for example using log4net I'm used to configure the logging subsystem in the Startup of the test by the api, and I create an appender that write just everithing on the console. You can't Insolate configuration by IoC since each possible logging system does not necessary share a contract for the Configuration part.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM