Castle Windsor - Staging vs Production connectionString parameter for a Component
I've been struggling with this problem, and while something elegant would be preferred any old hack will do at this point :)
I have a repository that is registered something like:
<castle>
<properties>
<myConnStr>Data Source=COMPUTERNAME\SQL2008;Initial Catalog=MyDB;Persist Security Info=True;User ID=username;Password=password</myConnStr>
</properties>
<components>
<component id="MyRepository" service="DomainModel.Abstract.IMyRepository, DomainModel" type="DomainModel.Concrete.MyRepository, DomainModel" lifestyle="PerWebRequest">
<parameters>
<connectionString>#{myConnStr}</connectionString>
</parameters>
</component>
</components>
I am trying to set up my config file so that I don't have to modify the myConnStr property portion for the various deployment options. It's fine (even ideal) if I can only establish the connectionString once when the configuration is first loaded, but I can't figure out how to set this value when setting up my container.
If I wasn't using castle windsor I'd just have multiple connection strings defined like "connectionStringStaging", "connectionStringProduction" and choose the appropriate one via code based on my environment (computer name or URL). Ho开发者_如何学Pythonw can I do something like that with a castle windsor property? Modifying the 'parameter' for the component instead of the 'property' would be acceptable as well.
IWindsorContainer container = ...
container.Register(Component.For<IMyRepository>().ImplementedBy<MyRepository>()
.LifeStyle.PerWebRequest
.Parameters(Parameter.ForKey("connectionString").Eq(GetConnectionStringFromEnviroment())));
where GetConnectionStringFromEnviroment()
gets the appropriate connection from the <connectionStrings>
section of your config or anywhere you want.
If you need this to be in XML config instead of code, you could:
- write an
ISubDependencyResolver
for that specific parameter. - use defines and ifs (this is probably the easiest solution if you're already using a xml config)
I'd prefer a simple solution and not push the framework to perform magic for you. I would wrap connection string in another class to provide the right connection to your repositories and add that to the dependency tree.
public interface IConnectionFactory
{
public string GetConnectionString();
}
Pass this into your 'Repositories' instead of a string.
Can't you do something like ...
<castle>
<properties>
<dev>Data Source=COMPUTERNAME\SQL2008;Initial Catalog=MyDB;Persist Security Info=True;User ID=username;Password=password</dev>
<stage>Data Source=COMPUTERNAME\SQL2008;Initial Catalog=MyDB;Persist Security Info=True;User ID=username;Password=password</stage>
<production>Data Source=COMPUTERNAME\SQL2008;Initial Catalog=MyDB;Persist Security Info=True;User ID=username;Password=password</production>
</properties>
<components>
<component id="MyRepository" service="DomainModel.Abstract.IMyRepository, DomainModel" type="DomainModel.Concrete.MyRepository, DomainModel" lifestyle="PerWebRequest">
<parameters>
<connectionString>#{dev|stage|production}</connectionString>
</parameters>
</component>
</components>
Otherwise have a look at using the configSource attribute and storing the environment settings in 3 separate config files. http://weblogs.asp.net/fmarguerie/archive/2007/04/26/using-configsource-to-split-configuration-files.aspx
The configuration choice should be an explicit activity external to the codebase.
disclaimer: This is something I wrote
FWIW, It's possibly overkill for you, but I've written a deployment-system to handle situations like this (different configurations for different servers); it's called dashy. It's currently in development (but the version you can download should work, to a reasonable degree :P), so I don't recommend it for immediate live use; but feel free to give it a crack in a dev/staging environment and see if it's useful. It does more than what you need, but might be of interest :)
精彩评论