C# multiple settings files with same interface
I'm trying to create a program with two (or more) discrete sets of settings, that both conform to the same interface. Particularly I'd like to do something like the following, using designer generated settings:
IMySettings settings = Properties.A;
Console.WriteLine(settings.Greeting);
settings = Properties.B;
Console.WriteLine(settings.Greeting);
This would be trivial with Go's interfaces because any class(?) that provides the methods can be assigned, but how can I implement this in C#, with its strict interface开发者_开发技巧 implementation rules?
Note: C#/.NET 2.0
The Properties.Settings class generated in VS is not going to let you do this. Consider defining a simple DTO class and marking it up with XmlAttribute so that you can easily deserialize it.
You can use interfaces in C#, too.
However, you'll have to write a facade class if you still want to use the designer-generated settings.
I'm not sure if what you're asking is how to implement an interface in C#.
If it is, just make something like:
Public Interface IMySettings {
Public string Greeting {get;set;}
}
Then just have your "A" and "B" implement this interface and returns your desired greeting. As a result your Properties class will implement IMySettings as opposed to a straight class:
Public class Properties {
public IMySettings A {get;set;}
public IMySettings B {get;set;}
}
So instead of using "MySettings", your code would look like so:
IMySettings settings = Properties.A;
I'm not sure if you can do what you through the designer generated settings, but I don't use them often so I could be wrong. However, there is another way you could do this: creating your own ConfigurationSection.
Here is an example:
public class MyProperties : ConfigurationSection {
[ConfigurationProperty("A")]
public MySettings A
{
get { return (MySettings )this["A"]; }
set { this["A"] = value; }
}
[ConfigurationProperty("B")]
public MySettings B
{
get { return (MySettings )this["B"]; }
set { this["B"] = value; }
}
}
public class MySettings : ConfigurationElement {
[ConfigurationProperty("greeting")]
public string Greeting
{
get { return (string )this["greeting"]; }
set { this["greeting"] = value; }
}
}
And then your app.config/web.config needs the following:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="mySettings" type="Namespace.MyProperties, Assembly"/>
</configSections>
<mySettings>
<A greeting="Hello from A!" />
<B greeting="Hello from B" />
</mySettings>
</configuration>
There may be typos in that but the overall idea is there. Hope that helps.
You could use a custom code generator to insert your interface into the generated code (using the method here: http://brannockdevice.blogspot.co.uk/2006_01_22_archive.html). It's very easy and very tidy, but the problem is, if you are working in a team, then they would all need to update their registry to build the solution.
Another option, and probably the closest answer to your original question, is to create a generic properties class and then populate, possibly via an explicit cast -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
namespace ConsoleApplication6
{
// use this class if you plan to add lots more settings files in future (low maintenance)
class GenericProps1
{
public string TestString { get; private set; }
// single cast for all settings files
public static explicit operator GenericProps1(ApplicationSettingsBase props)
{
return new GenericProps1() { TestString = props.Properties["TestString"].DefaultValue.ToString() };
}
}
// use this class if you do NOT plan to add lots more settings files in future (nicer code)
class GenericProps2
{
public string TestString { get; private set; }
// cast needed for settings1 file
public static explicit operator GenericProps2(Properties.Settings1 props)
{
return new GenericProps2() { TestString = props.TestString };
}
// cast needed for settings 2 file
public static explicit operator GenericProps2(Properties.Settings2 props)
{
return new GenericProps2() { TestString = props.TestString };
}
// cast for settings 3,4,5 files go here...
}
class Program
{
// usage
static void Main(string[] args)
{
GenericProps1 gProps1_1 = (GenericProps1)Properties.Settings1.Default;
GenericProps1 gProps1_2 = (GenericProps1)Properties.Settings2.Default;
//or
GenericProps2 gProps2_1 = (GenericProps2)Properties.Settings1.Default;
GenericProps2 gProps2_2 = (GenericProps2)Properties.Settings2.Default;
}
}
}
精彩评论