> I am trying to solve a problem involving user-configurable "fields" on an > object. Typically, these fields are configured by each client, and it is > quite easy to access them programmatically - a quick example would be:
You could/should use an Expando like this: using System; using System.Collections.Generic; using System.ComponentModel; namespace Expando { public interface IExpandoField { object Value { get; set; } Type Type { get; set; } } public interface IExpandoRecord { IDictionary<string, IExpandoField> Fields { get; } } [Serializable] public class ExpandoTypeDescriptor : CustomTypeDescriptor { public ExpandoTypeDescriptor(ICustomTypeDescriptor descriptor) : base(descriptor) { if (descriptor == null) { throw new ArgumentNullException("descriptor"); } } public override PropertyDescriptorCollection GetProperties() { return GetProperties(null); } public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) { // once again, we just wrap them up so we get to handle them. ExpandoPropertyDescriptorCollection properties = new ExpandoPropertyDescriptorCollection(); foreach (PropertyDescriptor property in base.GetProperties(attributes)) { properties.Add(property); } return properties; } } [Serializable] public class ExpandoTypeDescriptionProvider : TypeDescriptionProvider { private TypeDescriptionProvider _base; public ExpandoTypeDescriptionProvider() { _base = TypeDescriptor.GetProvider(typeof(IExpandoRecord)); } public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) { // simply wrapping with our own descriptor return new ExpandoTypeDescriptor(_base.GetTypeDescriptor(objectType, instance)); } } [Serializable] public class ExpandoPropertyDescriptorCollection : PropertyDescriptorCollection { public ExpandoPropertyDescriptorCollection() : base(null) { } public override PropertyDescriptor Find(string name, bool ignoreCase) { return base.Find(name, ignoreCase) ?? new ExpandoPropertyDescriptor(name); } } [Serializable] public class ExpandoPropertyDescriptor : PropertyDescriptor { private string _name; public ExpandoPropertyDescriptor(string name) : base(name, null) { _name = name; } public override bool Equals(object obj) { ExpandoPropertyDescriptor other = obj as ExpandoPropertyDescriptor; return other != null && other._name.Equals(_name, StringComparison.InvariantCultureIgnoreCase); } public override int GetHashCode() { return (base.GetHashCode() * 37) ^ _name.GetHashCode(); } public override bool IsReadOnly { get { return false; } } public override void ResetValue(object component) { // do nothing... return; } public override bool CanResetValue(object component) { return false; } public override bool ShouldSerializeValue(object component) { return true; } public override Type ComponentType { get { return typeof(IExpandoRecord); } } public override Type PropertyType { get { return typeof(object); } } public override object GetValue(object component) { return ((IExpandoRecord)component).Fields[_name].Value; } public override void SetValue(object component, object value) { ((IExpandoRecord)component).Fields[_name].Value = value; OnValueChanged(component, EventArgs.Empty); } } } -- "Your lack of planning DOES constitute an emergency on my part... so PLAN BETTER! " Marc C. Brooks http://musingmarc.blogspot.com =================================== This list is hosted by DevelopMentor� http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com