Enterprise Library : Configuration Part 1.1.3 - ConfigurationContext
Last week I did a podcast (why do we call it that when we use the WMA format?) with Ron Jacobs on the ConfigurationContext. I know that the talk was abstract and probably a little hard to follow and I hope to clear that up today with another explanation and samples.
I want to start off by saying that we intentionally did not document this “feature” because: a) we ran out of time , b) we knew it was a hard concept to cover, and c) I didn’t think people would be that interested (see what you get when you assume things).
What is the ConfigurationContext ?
Glad you asked. The ConfigurationContext is where your configuration data lives when it is loaded from storage and is the interface for read and writing this configuration data. It also serves as the interface for reading and writing the meta-data configuration. It has an internal cache and builds your data based on the defined meta-data (if you want to see this, look at the ConfigurationBuilder class). Some of you that are familiar with the Configuration Library are probably scratching your head and thinking “wait a minute, I thought that is what the ConfigurationManager was for…”. Well, you would be right. Think of the ConfigurationManager as a ConfigurationContext that uses the app.config / web.config file for it’s meta-data storage. You can use the ConfigurationManager for “most” of your ordinary needs, but the ConfigurationContext exists so when you have to do something that is extra-ordinary (80/20 rule) . The ConfigurationContext allows you bypass normal operations and take full control. I do want to warn you that by doing this, you are taking on a greater responsibility.. but relax, it is not that hard.
The Setup
There are a couple of main scenarios that the ConfigurationContext supports: 1) using a different file (not app.config / web.config) for reading/writing meta-data configuration; 2) allows you to use configuration that does not need any type of backing store and can be created dynamically within your application.
Most people don’t have a problem using their app.config or web.config for storing there meta-data configuration. An example where this could be a pain point is when you are using COM+ on a Windows 2K box and you don’t want to store you configuration in the dllhost.exe.config file. You don’t have to do that anymore. You can create your own ConfigurationContext based on a different file. The file has to follow the same schema as the app.config / web.config file, but other than that you are free. The following is an example of how you would create a ConfigurationContext based on a file:
1: ConfigurationContext context = ConfigurationManager.CreateContext(@"c:\myconfig.config");
2: // do something cool with the context, it contains all the meta data from the file
Another thing you might want to do is not have any configuration defined and completely define it in your application based on data gathered from other systems. The ConfigurationContext helps you do this as well. There are a few ways to approach this problem. I will try and describe each of them followed by a small example.
- The first way to do this is using the ConfigurationDictionary object. The ConfigurationDictionary is just a collection of name value pairs that are the section names and configuration settings objects. You load up the ConfigurationDictionary with your settings and then create a ConfigurationContext based on these settings. Internally we just add these values to the cache and use these settings when you request a section of configuration.
- Another way to do this is having a little bit of knowledge that since we cache everything for you, knowing that, you can change the cached values under the covers and know that since everything is a reference in .NET, you will get the changed values every time that you request them.
See this post for examples on how this works.
How does this work with the other Blocks in the Library?
Here is where the fun begins. Because you are taking a little more control of the situation yourself, you have to bypass the facades we put on top of the blocks. Now that you have a context you can tell the block “hey, I want you to use this set of Configuration.”.
Each block has a factory class that accepts a ConfigurationContext in it’s constructor. So instead of working with the DatabaseFactory you will use the DatabaseProviderFactory (sneaky huh) to create your Database. This is exactly what the DatabaseFactory class does for you, but assumes you want to use the default ConfigurationContext. Here is an example:
1: // create a specific context
2: ConfigurationContext context = ConfigurationManager.CreateContext(@"c:\myconfig.config");
3:
4: // create the factory with the right context
5: DatabaseProviderFactory factory = new DatabaseProviderFactory(context);
6:
7: // create the named instance of the database
8: Database db = factory.Create("SalesDB");
9:
10: // get some data from the sales database
Now I admit, what would have been better is for us to add a member to the DatabaseFactory class to do this work for you accepting the context. Hindsight is 20/20 . Of course, since you have the source, you could do this as well.
As Forest Gump would say, “Thats all I got to say about that.” (I am from Birmingham, AL not Greenbo ). I hope this clears up the podcast I had with Ron. If you have any questions please ask. The best place is at the message board on the workspace so everyone can benefit from the answers.
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm.
Now playing: 311 - Omaha Stylee
Comments
- Anonymous
March 02, 2005
OK, now is time to make public methods like:
internal static byte[] EncryptSymmetric(string symmetricInstance, byte[] plaintext, ConfigurationContext context)
right now I have to duplicate the Cryptographer source code for to be able to use my own ConfigurationContext ;) - Anonymous
March 09, 2005
Hi Scott,
I'm posting this on your weblog because GotDotNet workspaces has been choking this afternoon when I try to post there, and since you deserve the credit for EL Configuration:
I'm looking over the Security Application Block, because I want to use it to manage all of my ASP.NET authentication for all of our applications. I'm building a centralized Intranet portal that will handle Authentication and Authorization, then present the user with a list of the web applications they have access to.
Hence, we have multiple applications, each with different roles. So, for example, User1 is a User in App1, Developer in App2, etc.
There's 4 tables: Users, UserRoles, Profiles, and Roles. To manage the 1-many relationship between Users and Applications, and the 1-many relationship between Applications and roles, I (think) I'd like to add two tables: Applications and ApplicationUsers which map Users->Applications->Roles.
Unfortunately, looking at EL config RuleProvider, that has R:<your role> baked in, thus I won't be able to manage a rule that says:
Allow Role A to Print in Application B
without, of course, trying to extend EL/rewrite EL Config
So it looks like a workaround would be to have a bunch of AppRoles in their, e.g. App1User, App2Admin, etc. Unfortunately, I really have 4 or 5 defined roles per application, so this is non-normalized.
Is there a better way of doing this?
Thanks, and cool stuff! - Anonymous
March 11, 2005
Scott. First thing, the Application Blocks are awesome. We're in the process of adopting and building our new/rewritten code base starting with the codebase from the Enterprise Blocks. Had a quick question on the SQL Storage Provider, Im not sure where to begin in order to store our Configuration Block settings in a SQL Database after patching the Configuration block? Can you post a code example or refer to an example of how to do this using the Enterprise Console? Any help would be greatly appreciated. - Anonymous
March 13, 2005
Excellent explanation. I want to use the same thing for logging and instrumentation. "Each block has a factory class that accepts a ConfigurationContext in it’s constructor" --> which is this factory class for logging block?
I tried with LogWriter and was able to log it, but I cannot trace it with "Tracer". It fails to load the configuration file, and when I quickwatch "configFile" for Current.Builder (ConfigurationManager.GetCurrentContext), it is pointing to machine.config.
Am I doing right thing? - Anonymous
March 15, 2005
Continuation of my earlier thread:
I think I need to explain this more clearly. This is how exactly I create LogWriter:
context = ConfigurationManager.CreateContext( @"E:ELPROJECTSEL-BLOCK-CONFIGSLOG-INSTRU-DALDAL-LOG-INSTRUMENTATION.config" );
LogWriter writer = new LogWriter( context );
Unfortunately, after CreateContext, ConfigurationManager does not maintain this and also there is no way you can set Current Context, and therefore when I say ConfigurationManager.GetCurrentContext, it returns me the context which reads configuration from machine.config and not from my config file.
Hope this helps to understand issue more clearly.
Regards,
Shrini - Anonymous
March 29, 2005
2: // do something cool with the context, it contains all the meta data from the file
is confusing us. The solution is to directly call context:
Object myConfig = context.GetConfiguration("EditorSettings");
all is done.
Probably there is some difference calling this context and configmanager.
Guangming