Accessing Properties.Settings userSettings from a DLL
A component of the GUI of my main application is its own project, and th开发者_运维知识库e main application just uses the .dll of the GUI component when running. Since the userSettings
are stored in the GUI component's app.config
, which the main app does not copy, I cannot save userSettings (no user.config created).
The possible ways around this I see are either being able to store the component's userSettings
in an external config file (referenced by its app.config
) that is copied to the main app's directory at runtime, or somehow putting all the userSettings
at the main app's level (since its .exe.config
is copied) and accessing it from the GUI component.
However, I have not been able to get either of these methods to work for saving the userSettings
. Any ideas? If any clarification is needed, please let me know.
You should be able to move the Settings
from the main project Properties to the Properties of your GUI component DLL (or create a Settings.dll
if you prefer).
Then reference this DLL from your main application and add using
statements so you can access Settings.Default
. You then have to change the access modifier of the settings file. This is a little non-obvious but explained in the MSDN documentation. Here's a screenshot:
Once you change this to 'public' you can just read the settings from anywhere across your application.
Warning: Don't have more than 1 Settings per running application because the implementation is a singleton and you'll get unexpected results. If you have one copy of Settings it doesn't need to be in the .exe dll - it can be wherever you want it to be.
I assume you're not trying to re-use across applications.
Ah - the dreadful Properties.Settings!
There are several ways round this but all involve some rework.
Simplest - use appsettings instead of ApplicationSettings: Copy the appsettings required into each application that uses it.
Pros: easy, Cons: Config settings everywhere!
Create a custom Config Section: Lots of articles on this - see http://joelabrahamsson.com/entry/creating-a-custom-configuration-section-in-net for example.
Basically you'd then have your separate config file that you'd copy into each deployable that required it - simply reference the assembly where you create your Configuration Objects in each deployable that needs it, and update the application config file to reference the included custom config file.
Pros: Tidy, you can wrap validation inside the Configuration Object, Tidier config files, Cons: Takes a bit longer to set up.
There are others - including storing values in an XML file and deserializing it to a class at runtime. Using the same approach but storing in a database instead. etc. etc.
Here is how I approached a solution to this problem. Assume we're building MyDll.dll and we want to configure it with a MyDll.dll.config file. First, take snippets of the sections of the MyDll.dll.config file that contain the property settings.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyDll.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<MyDll.Properties.Settings>
<setting name="MySvrName" serializeAs="String">
<value>MyServer</value>
</setting>
<setting name="MyDbName" serializeAs="String">
<value>MyDb</value>
</setting>
</MPMLaborService2.Properties.Settings>
</applicationSettings>
</configuration>
Create a new class in the MyDll project called something like ConfigReader.cs and delete the default class code, but leave the namespace. Copy the XML above (from your project) and use Visual Studio Edit -> Paste Special -> Paste XML as classes into that class. This will build classes to read/write the config file.
Add these 'using' statements to the class or classes where you want the constructors to read from the config file:
using System.Xml.Serialization;
using System.Reflection;
using System.IO;
Declare a 'config reader' at module level or in the constructor:
private configuration _Cfg = null;
A few other variables will also be necessary:
private string _SvrName = "", _DbName = ""; // Module level
string path = "";
XmlSerializer serializer = null;
configurationApplicationSettingsSetting stg = null;
Put this in the constructor to read the settings:
path = Assembly.GetExecutingAssembly().Location + ".config";
if (!File.Exists(path))
{
throw new Exception("Config file not found:\r\n" + path);
}
serializer = new XmlSerializer(typeof(configuration));
using (StreamReader sr = new StreamReader(path))
{
_Cfg = (configuration)serializer.Deserialize(sr);
}
if (_Cfg.applicationSettings.MyDllPropertiesSettings == null)
{
throw new Exception("Property settings not found.");
}
stg = _Cfg.applicationSettings.MyDllPropertiesSettings
.FirstOrDefault(x => x.name == "MySvrName");
if (object.ReferenceEquals(stg, null))
{
throw new Exception("Can't find setting 'MySvrName'");
}
_SvrName = stg.value;
stg = _Cfg.applicationSettings.MyDllPropertiesSettings
.FirstOrDefault(x => x.name == "MyDbName");
if (object.ReferenceEquals(stg, null))
{
throw new Exception("Can't find setting 'MyDbName'");
}
_DbName = stg.value;
So long as you have permission to read the config file co-located with the MyDll.dll file it should work pretty much like you would hope it would.
精彩评论