开发者

How would I create composite settings for an application?

What I would like to do is have a versatile settings class that I can use in a composite application. As I add features and components and compose the application using MEF & Prism I would like to have a settings window that automatically loads the settings interface of each of the modules into a window (using Prism & MEF)

There are many different ways of dealing with settings, and the one that appeals to me is something along the following:

public class AppData : ApplicationSettingsBase
{
  [UserScopedSetting()]
  [DefaultSettingValue("true")]
  public bool Clipboard
  {
    get { return ((bool)this["Clipboard"]); }
    set { this["Clipboard"] = (bool)value; }
  }
}

It allows me to set a default value and I am assuming that if the application does not find the .settings file then it will create one with the defaults. However I would need to write a bunch of custom code for each modules settings section and either create a unique dialog for each module or try to have a settings manager that manually loads them all in.

There are some settings that would have multiple values as well and it does not look like the above example would be able to accomodate that. What if I had a setting that stored a list of something? For example if I had a setting that was ValidBlock, and at the start there are two blocks that could be valid but in the future there may be a need to add more? Can you have a setting that is a list and specify multiple default values for that setting?

So would it be acceptable to create a Isettings interface that somehow used ApplicationSettingsBase so that I can use MEF to find all Isettings implementations in all the modules in a directory and then compose a dialog with tabs for each implementation it found? In the Isettings interface I could have some basic properties such as Name and whatever else would be needed to lab开发者_Python百科el and describe the module in the MEF WPF window.

The only other thing I do not like is that there are strings and attributes all over the place. Is there a way to deal with settings in a fluent way? I am thinking along the lines of having a ISettings implementation that you would explicitly code a setup something like the following:

public class AppData : ISettings
{ 
    Setting Clipboard = new Setting();
    Clipboard.Scope = SettingScope.User;
    Clipboard.SettingType = List<String>;

    List<String> DefaultClipboards = new List<String>();
    DefaultClipboards.Add("FoxClipboard");
    Clipboard.DefaultSetting = DefaultClipboards;
}

I know the above is not exactly syntax correct, and I do not think that the Clipboard.SettingType would hold much water but its to give an idea of what I am thinking. So if something like this can be achieved while maintaining the creation of a settings file in the event one is missing that would be ideal. As well with something like this MEF can find all the ISettings implementations and create a tab for each one, and then add each Setting based on setup of it in the code.

Is this the right track to be on? Is there a framework or project out there that I have missed that handles what I am aiming for? I am thinking there is probably a better way than what I have outlined?

I am sure this question has come up in composite application development but I have not found a framework or an answer that outlines this scenario.

I have been able to create a loose coupled composite application and dynamically wire up my modules using MEF & Prism but I have not been able to find a satisfactory way to deal with settings in a composite way.


I tackled something similar for one of my applications at work. We leaned further towards your second idea, where there is simply a base settings interface "ISettings" that we used for MEF composition.

We created a custom export provider to deal with loading settings, and had a manager to save out the settings using some serializer.

For the UI, we had modules with user facing settings also export a "settings workspace" that we would load into the settings UI. Using reflection, we wrote a method that will make a deep copy of a settings object so that we could do direct mvvm binding to the cloned object (for cancel functionality), as well as take an object and copy it's properties back.

The reflection was to allow for a generic clone/copy without writing code for every settings object.

Also, one thing that we did that I still love to this day for data model binding is the "INotifyPropertyChanged" interface. Our base ISettings object requires it. This allows not only the settings UI to directly bind to settings and listen for changes, but when we hit apply or ok, all of our data model that needs settings registers for the prop changed event, so they all automatically get notified when a setting has changed.

Check out Property Observer if you plan on doing the notify route. This application has been deployed and I still feel like our settings framework is wildly successful.

If you need, I can provide further detail in certain areas.

Hope this helps!


Disclaimer: I have no experience with custom implementations of ApplicationSettingsBase so I can not assist with its actual implementation, nor positively say that this approach will work. However, what I propose might be a path worth exploring if you really want to use ApplicationSettingsBase.

First of all, ISettings can not inherit ApplicationSettingsBase, because interfaces can only inherit other interfaces.

My proposal is to create a custom ApplicationSettingsBase implementation that is parameterized with an instance of ISettings. That way, whenever you recieve an ISettings from your components, you instantiate a new CustomAppSettings (see below) and associate that with your component.

Since ApplicationSettingsBase uses a string-to-object key value pair mapping, I propose an interface that does the same.

public interface ISettings
{
    Dictionary<string,object> Values{ get; set; }

    public object GetDefaultValue(string key);

    // Whatever else you might need
}

public class CustomAppSettings : ApplicationSettingsBase
{
    public ISettings Settings { get; set; }

    public override object this[string propertyName]
    {
        get
        {
            return this.Settings.Values[propertyName];
        }
        set
        {
            this.Settings.Values[propertyName] = value;
        }
    }

    // There will be more implementation work for this class I'm sure
}

In addition you would need a serialization mechanism for your ISetting instances.

Edit: Fixed some code syntax errors

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜