I am designing an enterprise-level application and my Visual Studio solution is composed of multiple projects.
The application has the following cross-cutting concerns:
- Logging
- Configuration
- Data access
I want to achieve:
- Abstraction from concrete service implementations. The entire solution should work with the services via interface. There should be a single, centralized place, where I bind the interfaces to concrete implementations.
- Common way of 'finding' and referencing cross-cutting components. I don't want the developers to have to search for a 'how do I instantiate/reference?' example within the solution
- "One-time only" and lazy execution of expensive initialization operations such as: configuring the logger, reading the app configuration
Below is a pseudo-code mockup of my Business layer.
Catalog pattern & Singleton Pattern
Allow me to easily 'locate' and use core services, by Interface, executing expensive repetitive operations such as the logger initialization, application configuration reading and etc, ONLY ONCE, lazy.
class Services
// Initializes only once
singleton ILogger Logger {
var logger = ServiceFactory.GetLogger();
logger.Configure(Services.Configuration.LoggerConfig);
return logger;
}
// Initializes only once
singleton ApplicationConfigurationManager Configuration {
var appConfigManager = new ApplicationConfigurationManager();
appConfigManager.Initialize();
return appConfigManager;
}
// New instance every time (necessary for 'cleaning up' the database context)
non-singleton IDataRepository DataRepository {
return ServiceFactory.GetDataRepository();
}
class ApplicationConfigurationManager {
public Initialize() {
var dataRepo = Services.DataRepository();
var keyValuePairs = dataRepo.GetConfigurationKeyValuePairs();
// ... use keyValuePairs to initialize own properties
}
}
Now I can use the logger as:
Services.Logger.WriteMessage("hello");
or the configuration as:
Services.Configuration.TimeZone
Factory pattern
Allows easy swapping of implementations (e.g. switch from log4net to nUnit), without the burden and overhead of actual Dependency Injection. As a matter of facts, I prefer my application to have direct References to the class-library DLLs, for the reason of build validation, instead of assuming that the injection configuration was correct.
That would be the only place where actual implementation classes are referenced.
class ServiceFactory {
IDataRepository GetDataRepository() {
return new EfDataRepository();
}
ILogger GetLogger() {
return new Log4NetLogger();
}
}
Do you see a general flaw with this approach?
Aucun commentaire:
Enregistrer un commentaire