> 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