How would I create composite settings for an application? - c#

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 label 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

Related

Passing config values as parameters to an instance method C#

I come across this regularly when refactoring code. Say I have a base class and I read some configuration parameters and stuff them into properties like this
public BaseClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
And then I call a method in another class like this
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod(_property1, _property2, _property3);
Is it better to do that? What if I only needed the AppSettings values inside of the OtherClass class? then I could just load them up as private props and initialize them in the constructor and the referencing class/caller wouldn't need to be concerned with the settings.
public OtherClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
My implementation would then simply be
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod();
This one bugs me but I am not really sure why. Which is a better practice and why? And I apologise I am missing something obvious. It happens sometimes lol.
Thanks -Frank
In my view, it depends on what goal of your class.
If class belongs to domain classes, so there is no need to have a dependency to ConfigurationManager class. You can create a constructor and supply necessary data:
public class FooClass()
{
public Property1 {get; private set;}
public FooClass(string property1)
{
Property1 = property1;
}
}
If FooClass belongs to Service Layer, then, in my view, it is eligible to have a dependency to ConfigurationManager class.
I can't really comment on "better" as that's quite subjective, but it's at the very least factual to say that passing the parameters into the method, rather than having the method go and get them itself, is a form of dependency injection. Dependency injection has advantages in that it reduces the number of things the class has to know how to do/reduces the number of other classes any given class needs to do its work. Typically in OO design we look for ways to reduce the dependencies a class has on other classes. You might also see the concept referred to in general as low coupling. Classes that are not highly coupled to other classes are easier to reuse as independent modules within multiple programs
In your example, OtherClass (and/or BaseClass) needs to know what a ConfigurationManager is, which means it needs a reference to its namespace, needs to have system.configuration.dll available on the target etc just so that it can go and get some basic things (strings) that contain info necessary to do its work. If you instead give the strings to the method then it can do its work without knowing what a ConfigurationManager is - you can use it in an app that doesn't even have a ConfigurationManager anywhere, maybe because it gets its config from a database or perhaps it's part of a unit test that gets some contrived data directly from hard coding to ensure a given result is always obtained
When you're down with the concept that the data a class needs to do its work can come from above it starts to make more sense why systems that pass data around like this can work with an inversion-of-control container; essentially software that creates instances of objects for you according to some preconfigured rules about where to get the data that should be passed in. An IoC container can look at an object and decide what arguments to pass to (e.g. its constructor) based on a consistent set of rules, and take another step towards removing dependencies by further reducing use of the word "new". Think of it like writing a config file to describe which of your objects need what instances of other classes to do the work. You craft your IoC container setup so it makes one IniFileConfigSettingsProvider instance and then provides that instance to any object that needs some kind of IConfigSettingsProvider to do its work. Later you switch away form ini files and go to Xml files. You create a class called XmlFileConfigSettingProvider, register it with the IoC and it becomes the new instance that is passed to any class needing an IConfigSettingsProvider. Critically, you made another class, registered it with the IoC and then it gets used throughout your program but you never made an instance of it yourself
If you ever heard the phrase "new is glue" concepts like this are generally what it alludes to - when your OtherClass says var x = new ConfigurationManager... x.Settings["a"].... the use of the word new has suddenly hard wired it to needing a ConfigurationManager; it can't function without knowing what it is. The strive these days is generally to have a class accepting a "passed-in provider of settings that complies with some interface" or "passed-in primitives that are settings" - things that are either implementation specific but obey a generic interface, or ubiquitous in the language and need no special imports respectively. Perhaps either of your mentioned approaches bug you because deep down you feel that neither of them need to depend on ConfigManager; whether they both need settings or not, they can get them passed in, from something higher up the chain that should be making the decisions as to what settings to use
There will be pros and cons of every design and coding choice. As they say, same pattern may not fit everyone. So one has to customize based on need.
Mainly, decision should be based on use cases of your application. Let me provide few scenarios to describe it. Suppose items configured in AppSettings will not change in life-time of the your application then you can have an approach in which dependencies with AppSettings are least. In particular an approach as var foo = otherClass.SomeMethod(_property1, _property2, _property3);. This matches with OOD principles as classes will focus on business logic.
But if you see add/modifying/deleting items (even in rare situations) during life time then above approach would be difficult to maintain. For example without restarting your application/WebServer if AppSettings needs to be reloaded based on certain conditions. One may argue why such settings will be kept in AppSettings, which is very valid too. If your application demands such scenarios then it would be better to use ConfigurationManager.AppSettings without worrying about dependencies. One can opt to extend it have wrapper class (Singleton pattern) to manage and provide access to ConfigurationManager.AppSettings.

Interface in C# settings

I have color scheme for my code editor in a settings file in the project. I have a several similar settings files each containing different color scheme.
To make those settings selectable on runtime, I need them to implement ColorScheme interface.
So far so good, code works fine, with only one major annoyance: each time settings are changed, the interface part is removed from Designer file, so the code doesn't find them anymore.
Is there a way to force code generator to add my interface to generated class? Or is it other workaround for this? I tried to make designer file readonly, but then I see lots of annoying VS dialogs.
Without the interface, I can't cast settings class on anything. I could probably read its properties via Reflection, but this approach looks like an ugly hack.
You could go for an "extension" using a partial class for your settings, that include the interface :) (It should be in the same namespace/assembly as your settings file is). Any changes to the settings do not interfere with your self created partial class
public interface IHaveInterface
{
void Hallo();
}
internal partial class Settings : IHaveInterface
{
public void Hallo()
{
Console.WriteLine("Hallo");
}
}
after which i can access the hallo inside the Properties.Settings.Default
Properties.Settings.Default.Hallo();

Designing a contract for plugins

I was thinking about designing a proper contract for future plugins creation for an application I'm currently working on. Basically the idea is to define an interface, but I want the application to be aware of plugins that currently presented to the system and to show the user a nice list of plugins with their names and a brief descriptions which ofcourse the developer of the plugin should provide, the user of the application shouldn't be able to alter this easily so an additional config file is not an option. I don't want to use the class name of filename of the assembly for this. Also I think that it should be accessable without instantiating the plugin, but maybe through reflection, something like: assembly.GetType(type).GetProperty("Name").GetValue(null, null).ToString();. Ofcourse I could provide some logic to check for existance something like if(assembly.GetType(type).GetProperty("Name") != null), but this is not a good idea either, because if the property does not exist the end user won't have an idea of what that plugin does, not even what it's name is.
Now, it should behave like a static property, but static is not overridable so it seems that I cannot declare it as a part of an interface nor in an abstract class. Maybe I'm on wrong way, and it only looks like a static property and I can achive this functionality through another approach. So the brief question might be "How to enforce the third party developer to provide some meta information about his plugin". Please advise.
You could try with two interfaces:
IAddIn for be the main interface that all add-ins will implement.
IAddInInfo for be the interface providing the metadata of the add-in (name, publisher, description version etc.)
Each add-in should implement both of these. An IAddInInfo implementation could be like this:
public class ScannerAddInInfo : IAddInInfo
{
public string Name { get { return "Scanner"; } }
public string Description { get { return "Add-in for acquiring images from a scanner device"; } }
}
To ensure that all implementations of add-ins come with metadata, you can make IAddIn a generic interface like:
public interface IAddIn<T> where T : IAddInInfo
{
T Info { get; }
//Continue with the rest of the members you would want every add-in to have.
}
Then the scanner add-in implementation would be:
public class ScannAddIn : IAddIn<ScannerAddInInfo>
{
private ScannerAddInInfo _info = new ScannerAddInInfo();
public ScannerAddInInfo Info { get { return _info; } }
//Continue with the rest of the IAddIn implementation.
}
Then you could load the add-in assembly from a special add-in folder and create instances of the types implementing IAddInInfo and show the info from the discovered add-ins in your application. Note that no add-ins are created yet. To do so you will need to add some more reflection to find the types implementing IAddIn<ScannerAddInInfo>.
To make this simpler you could add the add-in type name to the IAddInInfo interface or something like that.
The only drawback to this approach is that you will have to load all assemblies found in your special add-in folder even if they do not include any add-ins.
To avoid this you could try Mono.Cecil. You then will have to do something like this:
AssemblyDefinition ad = AssemblyDefinition.ReadAssembly(assemblyPath);
foreach (TypeDefinition td in ad.MainModule.GetTypes())
{
if (td.BaseType != null && td.BaseType.FullName == "MyNamespace.MyAddInBase")
{
return true;
}
}
To load the assemblies you can use Assembly.LoadForm and to create instances of the add-ins and add-in infos, one of the Activator.CreateInstance overloads.
Good luck.
To add some 'meta data' to your plugins, you can use attributes. Create a custom attribute for your plugins and read out the information with reflection and show it in your application.
More info about attributes:
Creating Custom Attributes (C# and Visual Basic)
Accessing Attributes by Using Reflection
The thing you should do is basically define your interface and expect other people to implement their concrete classes and give that runtime object to you somehow (your predefined methods, configuration etc.)
But there is some mechanism called dependency injection. That allows you to define your interface and your entry points while a "system" takes care of matchmaking your entry points and implementers' concretes. There is "System.ComponentModel.Composition" namespace for this purpose.
I knew there was a framework called "Unity" doing such job. I guess composition namespace is somewhat a simplified version of unity. You can check help for "ImportAttribute" and "ExportAttribute" classes for some cue.

Reflection-based injection vs. dynamic proxy: Practical considerations?

I'm working on some framework-ish code designed to execute a huge number of operations (hundreds of thousands), all of which use the same basic components, but need to accept operation-specific configuration data from an external source.
Assume for the moment that there's a configuration repository which, given the appropriate list of setting names, knows how to load these settings efficiently and store them in a type like the following:
public interface IConfiguration
{
dynamic Get(string key);
void Set(string key, dynamic value);
}
What I'm planning to do is implement either some fluent mapping syntax or just decorate the component classes with attributes like so:
public class MyComponent : IActivity
{
[Configuration("Threshold")]
public virtual int Threshold { get; set; }
[Configuration("SomeKey", Persistence = ConfigPersistence.Save)]
public virtual string SomeSetting { get; set; }
}
You get the picture... hopefully. What's important to note is that some properties actually need to be saved back to the repository, so conventional DI libraries don't work here; and even if they did, they're blunt instruments not designed to be spinning up hundreds of thousands of components and loading/saving millions of attributes. In other words, I don't think I'm reinventing the wheel, but if somebody wants to try to convince me otherwise, feel free.
Anyway, I'm considering two possible options to handle the "injection" of configuration data into these component instances:
Plain vanilla Reflection - scan the type for configuration attributes and save the member info (along with the config key) in a static dictionary. Then use reflection methods such as PropertyInfo.SetValue and PropertyInfo.GetValue for the injection and extraction (for lack of a better term). This is similar to the approach used by most DI libraries.
Use a dynamic proxy such as Castle and hook up an interceptor to the decorated properties, such that instead of referencing private/autogenerated fields, they reference the IConfiguration instance (i.e. the get method calls IConfiguration.Get and the set method calls IConfiguration.Set). This is similar to the approach used by NHibernate and other ORMs.
The full implementation may end up being a fair amount of work, so I don't want to go too far down the wrong path before realizing I missed something.
So my question is, what are the pros/cons of either approach, and what are the pitfalls I need to avoid? I'm thinking in broad terms of performance, maintainability, idiot-proofing, etc.
Or, alternatively, are there other, quicker paths to this goal, preferably which don't have steep learning curves?
Dynamic proxy is much better approach. Define a "configuration" interceptor that injects the value from the configuration into your component (preferably lazily). Using Dynamic proxy, I'd also implement a generic IDisposable interface to your proxied Component, so that when the object is disposed or GC'd, it will persist configuration values based on the Peristence flag set in your attribute.

Passing objects to a UITypeEditor

I am currently hoping to use a PropertyGrid to allow users to edit some of my classes, however I've hit a wall with passing objects to the UITypeEditor(s) they use. When the user presses the drop down I want to show a listbox of already loaded textures to choose from, if they want to use a texture the application hasn't loaded yet they can click a button to choose one from a file dialog. In case I make no sense here a mock of the form:
.
My problem: To fill the listbox I need access to the class that manages the list of resources from the UITypeEditor.
Now I've solved this problem for my own classes by giving them a reference on creation to their managing object. In the UITypeEditor I then use that reference to access what I need. However I can't do this for classes I haven't written, such as the XNA Texture2D class.
Here are what the classes I'm using look like:
class StaticGeometryChunk
{
// Geometry data to draw with. Contains a reference to its managing
// class for use in its UITypeEditor.
public GeometryData { get; set; }
....
}
class Material
{
// These are XNA classes. I can't just add a reference to its managing
// class (I think?).
public Texture2D Texture1 { get; set; }
public Texture2D Texture2 { get; set; }
....
}
I've been looking at my options and they seem to be:
Make the managing classes static.
I don't really want to do this. There are several managing classes as each resource is loaded differently. There are also classes that need to be created before these and are passed in.
Make the managing classes singletons.
I don't really want to do this either. It seems like a quick and dirty way to "hide" the problem instead of "solve" it. I also might want the option of having several managing classes in the future which the singletons eliminate.
Create a wrapper class which holds the reference to a managing class and its target (such as the XNA Texture2D).
This is currently what I'm thinking of doing. Its would be quite simple and quick to do but something about it nags me but I don't know what.
Any thoughts on the above or other methods to pass what I need into the UITypeEditor?
Thank you for reading.
In the EditValue method, you are given a context. Use context.Instance to access the object that holds your property. This object should also contain a property that gives you access to the list of things you want to display. You could test if context.Instance is ITextureProvider for example, then cast it and access the textures. Not sure if this makes sense in your design but let me know.
As an alternative you can try the following approach. I find it very elegant, because it does not require to store a list of available property values in the object. Therefore, for example, you can show one set of values on one form and another set on another.
Create an interface IYourDataProviderService.
Create an implementation of IYourDataProviderService, which knows the concrete data to provide.
Create a class implementing ISite. In GetService() method return an instance of class which implements IYourDataProviderService, if the serviceType parameter is typeof(IYourDataProviderService).
I left rest of ISite methods throwing NotImplementedException (except DesignMode property) and for me it worked, but probably this is not an ideal solution.
In 'Load' event handler assign your implementation to the Site property of your propertygrid.
Enjoy!

Categories