External config file to be used by multiple DLLs - c#

I have multiple DLLs that are used to read/write data into my database.
There is a presentation layer DLL and a data access layer DLL. I want these DLLs to share a set of the connection strings.
My idea is to store the connection string in a seperate DLL in the external configuration file. I'm not sure whether it's a good idea and whether I can reference that external DLL in both presentation and data access layers.
The other question is whether I should write a helper class to read the data from the external config file or whether I should be using built in .Net methods?
Thank you

Isolate the configuration file access code in a separate class. Make the configuration data (connectionstrings and whatnot) available via an interface on that class. Let the interface live in a shared assembly. Let any class that needs this interface get a reference to an instance of the configuration class via dependency injection. If you're not already using a DI framework I can highly recommend Autofac.
What have you achieved? Presentation and data access classes are now only dependent on a shared interface definition. They don't care what the implementation of that interface is, whether it reads connection strings from web.config, machine.config or some other store. Even better, you can now more easily test your classes by faking the implementation.
Update: First, to illustrate making the configuration data available via an interface. Say we have the following conffiguration service:
public interface IConfigurationService
{
string ConnectionString {get;}
}
public class ConfigurationService : IConfigurationService
{
string ConnectionString {get;}
public ConfigurationService()
{
// load configuration
}
}
My data access class could use this class directly:
public class DataAccess
{
private string _connectionString;
public DataAccess()
{
var config = new ConfigurationService();
_connectionString = config.ConnectionString;
}
}
The problem with this approach is coupling. DataAccess is now directly dependent on the ConfigurationService class. Any tests we write for DataAccess will inadvertently be affected by the ConfigurationService class. Also, should we need to switch out the implementation of ConfigurationService it would require changes to DataAccess (and all other classes directly dependent on this class).
To solve this, we invert the dependency hierarchy and references an interface instead of the concrete class, like this:
public class DataAccess
{
private string _connectionString;
public DataAccess(IConfigurationService configurationService)
{
_connectionString = configurationService.ConnectionString;
}
}
The data access class is now oblivious as to what the configuration service implementation is and how that instance is created.

As far as I'm aware, DLL files cannot make use of .net config items like app.config files, so if you want your dll to be configurable through say an xml file, you'll have to write it yourself.

I can store the connection string in the machine.config, but once again not sure about all the implications....

Related

Can constructor initialization be used for dependency injection instead of having DI containers?

here's an example of what i am talking about
public interface IService<T>
where T : class
{
List<T> GetAll();
T GetById(object id);
.......... other methods here
}
public class Service<T> : IService<T>
where T : class
{
... implement interface here
}
public class ServiceClient
{
private readonly IService<User> _service;
public ServiceClient(IService<User> service)
{
_service = service;
}
public ServiceClient() : this(new Service<User>()){}
}
can someone tell me the difference between this and a Dependency Resolver? I normally Use SimpleInjector for Dependency Injection, I just want to know the benefits of the Container over doing the above..
Thanks
Update
okay lets say I have setup my Containers now and removed the 'this' constructor initialization, I Want to now Test ServiceClient
Let use MS unit test for snippet
[TestMethod]
public void Given_Something_Should_Success()
{
// Arrange
// how do i make an instance of this in a test without adding the 'new Service<User>()' part
ServiceClient client = new ServiceClient(new Service<User>());
}
and without changing my ServiceClient constructor to do this. Is it even possible to do that at this level? Sorry if this is a noob question i'm just trying to understand some things about it.
public ServiceClient(IService<User> service = null)
{
_service = service ?? new Service<User>();
}
See this line of code:
public ServiceClient() : this(new Service<User>()){}
Now the ServiceClient is aware of Service<User> class and the assembly where the ServiceClient is will not build without having a reference to the assembly where Service<User> class is located. Furthermore, if Service<User> has additional methods which are not in IServiceUser<User>, then the developer may do this within the class:
(this._service as Service<User>).SomeMethodNotBelongingToTheInterface();
Now one can argue that an irresponsible developer will do that sort of thing, but that is beyond the point here.
To be totally decoupled from the concrete implementations, you should never call new and leave this to the Composition Root. Both your classes and your assembly should only work with the interfaces and be totally unaware of the concrete implementations. This guarantees that you can plug any implementation at the composition root level, and everything will work.
This does not mean that even POCO classes without behavior should be behind interfaces but just classes that require plug and play sort of behavior.
If you follow this pattern, you can also create architectural diagrams within Visual Studio and instruct which layer can have references to which assemblies. During build, the build will fail (if configured to fail) if the developer creates a reference to an assembly they are not allowed to reference.
At the composition root level, it is up to you whether you want to plug the classes into each other using an IoC container or doing it manually. But why do it manually if there are good tools (IoC containers) which can do this for you. You can have one config file where all the test classes are and another where the real classes are. You can instruct your whole program to run with either configuration with just one line of code: This is what I mean by plug and play. The whole idea behind dependency injection, loose coupling etc. is that your classes should not have code which is written against a concrete implementation.
In Container you would register your class and interface.
Benefits are , you have one ioc class which will take care of providing you right type.
So you can program against interface.
and you do not need to new up in your code.
this gives you also flexibility when you have to manage scope or mock some class.
Here is some example how you register via IoC (Autofac)
builder.RegisterInstance(new ServiceClient())
.As<IService>();
What using a Container gives you is a centralised place in your application to specify how your dependencies should be resolved.
Imagine you have many classes that wants to inject the same implementation of IService. By using your approach above, you would have to write that same code for all of those classes. If you would have used a container, specifying it there would be enough.
Also, many DIs gives you more functionality for sharing instances, maintaining life cycles of your injections etc, provide dependencies to your dependencies etc.
This is called Bastard injection and you shouldn't do this because is totally against the purpose of dependency inversion: to create decoupled and maintainable code. If you use a default implementation it means that you have to reference the project that contains the implementation of your service. Or worst you probably create the implementation of your service in the same library where it lives the interface.
On the other hand you might have a good default implementation. For example you might define this interface:
public interface IClock
{
DateTime Now { get; }
}
The obvious implementation of this interface is
public class Clock : IClock
{
public DateTime Now => DateTime.Now;
}
I wouldn't use though a public constructor for this, I would inject it via a Property and leave the constructor for another implementation (maybe a mock from your tests). Also SimpleInjector I think would shout about having two constructors. It is a tool which made me to read more about these ideas.
When the IService's implementation is something that talks with a database, or HTTP service, or a remote one, or with 3rd party library or with file system, then these are good reasons for you create a separate project, reference the one you defined the interface, create the implementation, then in your place where you setup the simple injector, you can bind the interface with the implementation (which requires here to reference both projects). If on a later time you need a diferent implementation you can simply repeat the process and change the composition root.

SettingsProvider class - should it be in DAL or BLL project?

I have in my application layers: Web, DAL and BLL.
Where should I place SettingsProvider class (to get values from web.config)? I think it should be inside DAL project. Am I right?
public class SettingsProvider : ISettingsProvider
{
public string UploadImagesPath
{
get { return ConfigurationManager.AppSettings["UploadImagesPath"]; }
}
..............
}
I don't agree that there is a right layer for you to put that class since you reading values from the config file based on keys provided and it can be needed by one or all of the layers. In the case of all layers using this class, you can as well setup a common Class Library project and reference it in layers where it is needed.
Since settings are specific to Web application (because they are defined in Web.config) I think you should put it in Web application and somehow "send" them to BLL or DAL, wherever appropriate. And since you already have an ISettingsProvider interface defined, you could make a use of some IoC container and registering this interface on Web's bootstrap method (or sth like that). Or just send your ISettingsProvider (maybe static variable) arround into DAL and BLL from Web application.

Get connection string in class library project in a solution

In my .net 4 solution, i have two different projects- an web application project and a class library project.
In web application project, database connection string is in web.config file. I would like to access that connection string from class library project. Is it possible? if yes, how?
If there is any better approach to get connection string, please let me know.
To access it from your class library add a reference to System.Configuration then use System.Confinguration.ConfigurationManager.ConnectionStrings.
It's not ideal to read this from a class library. After all, can you say that your class library will always be consumed by something with a configuration file? Certainly not if you share it with other developers, especially of different platforms.
Consider:
IoC - use dependency injection to provide a dependency that contains configuration settings. These would be populated by the consuming library (web app).
Pass the settings to the class library when consuming elements that depend on them.
e.g.:
public class MyLibraryContainer
{
private string _connectionString;
public MyLibraryContainer(string connectionString)
{
_connectionString = connectionString;
}
}

Configuration settings placement in 3-layered application

In a standard 3-layered application (Winforms Ui, BLL, DAL) i need to have settings specific for each layer.
Should i use the Winforms application settings to include all of them or i should have each dll (BLL,DAL) come with their settings?
I need a simple solution and not in a database or custom xmls, also i need to provide multiple UIs for the same architecture.
Update: Currently i am leaning towards separate .config files for each layer, i just dont know if this is the best practice that will allow for most of future changes (changes in layers and/or multiple UI apps).
Outcome: I think i am gonna have a static singleton class in every project that i need settings. I am gonna populate them by the upper layer every time with the most suitable way.
Custom xml file is flexible approach but need a bit effort.
Use a separate library project only to serve for settings, its easier way as you may use default settings class to save/load settings but not very flexible for nested settings.
Put all settings with DAL since it live at root and all other projects (UI, BAL) reference it)
Every time I tried to use the built-in app.config file, I ended up implementing my own config solution due to shortcomings of the built-in solution. Implementing a custom xml-based solution is not complex. It is actually very easy.
Just put this base class into your solution:
[Serializable]
public abstract class ConfigBase<DerivedT> where DerivedT : ConfigBase<DerivedT>
{
protected string FilePath;
public string FileVersion;
public ConfigBase() { }
public void Save()
{
XmlSerializer xs = new XmlSerializer(GetType());
using (StreamWriter writer = File.CreateText(FilePath))
{
xs.Serialize(writer, this);
}
}
public static DerivedT Load(string filename)
{
XmlSerializer xs = new XmlSerializer(typeof(DerivedT));
using (StreamReader reader = File.OpenText(filename))
{
DerivedT config = (DerivedT)xs.Deserialize(reader);
config.FilePath = filename;
return config;
}
}
}
Then you can make your configuration file like this:
public class Config : ConfigBase<Config>
{
// put your variables here like below
public string DatabaseConnectionString;
public int numberOfConnections;
}
Use it like this:
// Load it like this
Config config = Config.Load(ConfigFileName);
// Save it like this
config.Save();
Feel free to use properties, arrays and other complex structures within the config file. It will all serialize automatically. Use XmlIgnore attribute if you do not want certain fields/properties serialized. With this solution you can have many different configuration files, but have a single mechanism to load and save them.
I often include a public static Config GenerateDefault(string ConfigFileName) factory method inside the Config file, which will produce a sample config with default values.
Don't forget to check if the file file exists and load it within a try/catch block.
An even better solution would be to use DataContracts, which allows you to serialize private members and provides good mechanisms for supporting different versions of DataContracts, but it is a bit more complex.
If all your layers are running in the same AppDomain (rather than, say, hosting the BLL/DAL in a WCF service), then the KISS solution is to include all the configuration information in the client's app.config file.
You can use a naming convention to distinguish settings belonging to each layer.
UPDATE
From comment:
Currently yes, but I would like to be free to change later even the DAL presentation (via WCF for example).
That's simple: when you move a logical tier into a different physical tier such as WCF, you move its configuration into the configuration file for the host (e.g. web.config if the host is IIS).

Access web.config from separate Class Library?

I'm looking for a good way to achieve the following:
I have a web application (MVC 3), with a separate Class Library that contains the back-end logic of a CMS that I'm making. This CMS uses NHibernate to connect to a database. I want the user to be able to configure the connectionstring (and eventually even the flavour of the database) in their web.config file.
What I'm looking for is a good way to get the connection string from the web.config file, even though the DLL is completely separate. Is this possible? Will I have to pass my connection string to my class library somehow? Or will I be able to access it when the application runs?
If I have to create some code in my web application to pass the connection string to my Class Library, how can I make this code as portable as possible, so I won't have to write it again for my next webapp?
Thanks a lot for any ideas you have.
You can pass in the connection string to the classes in the class library from the web site.
This is a better choice than trying to get the information directly from the configuration file, as otherwise you will have a dependency on the configuration file existing with the exact right key (making testing the class somewhat harder).
See this blog post for arguments against accessing configuration directly (which is very commonly done, but is not best practice).
You can access System.Configuration.ConfigurationManager from your class library. That'll give you access to the AppSettings and ConnectionStrings.
I have exactly the same setup with a FOSS project I'm involved with. It contains everything (even the Controllers and Global.asax.cs) in the 'Core' class library.
There's plenty of valid solutions, the one I opted for was to create a Settings class which is essentially a set of static properties, inside which you have:
public static string ConnectionString
{
get { return ConfigurationManager.ConnectionStrings["MYAPP"].ConnectionString; }
}
Note: make sure your class library has System.Configuration added as a reference.
Inside your Application (the class derived from HttpApplication) you pass the settings across, although there is nothing to stop you tighly coupling the NH setup with the settings class:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
SetupNHibernate();
}
public virtual void SetupNHibernate()
{
NHibernateRepository.Current.Configure(RoadkillSettings.DatabaseType, Settings.ConnectionString, false, Settings.CachedEnabled);
}
If this is any use to you, the source is here.
You can use the ConfigurationManager class to access items in your web.config or app.config file. However, in your class library, be sure to take in the key name of any appSettings and/or connectionString settings from the consumer (preferably in the constructor). This avoids the problem of you choosing a key name that the consumer is already using elsewhere.
Since you are using the class library to the MVC web application, it is accessible to the class library also. No additional settings are needed. Even though the class library when built giving a separate dll, it is referenced in the current project. So the connection string will be available to the class library also.
I'd go with something like Autofac to give you some IoC implementation which can store a settings interface for your connection strings. This would allow you to setup the value from the web.config on application start, or to set it within tests to a different value without your Class Library ever having to be coupled to a web.config.
You can add new Existing item from another project to your class library. Then change Build Action to Embedded Resource and Copy to Output Directory to Copy if newer on the Web.config file.
Web.config in another project
<configuration>
<appSettings>
<add key="MyConfigValue" value="Test" />
</appSettings>
</configuration>
Class library test file
var doc = XDocument.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web.config"));
var myConfigValue = doc.Element("configuration")
.Element("appSettings")
.Elements("add")
.FirstOrDefault(e => e.Attribute("key").Value == "MyConfigValue").Attribute("value").Value;

Categories