Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Using meta-data in .NET
Message
From
25/10/2007 16:53:16
 
 
To
25/10/2007 15:28:39
General information
Forum:
ASP.NET
Category:
Coding, syntax and commands
Miscellaneous
Thread ID:
01262116
Message ID:
01263828
Views:
10
Arrrgh. Is this what you need to do to add a property at runtime? Couldn't you just type:
MyControl.AddProperty('MyNewProperty', 'MyDefaultValue')?
Oh, wait, that's VFP syntax...


Pertti

>Alex,
>
>here is other sample to you which uses TypeDescriptor to add property at runtime.
>
>
using System;
>using System.Windows.Forms;
>using System.Collections.Generic;
>using System.ComponentModel;
>using System.Runtime.CompilerServices;
>
>static class Program {
>	[STAThread]
>	static void Main() {
>			Customer Customer = new Customer();
>			Customer.AddProperty<string>("Name");
>			Customer.SetValue("Name", "Alex");
>			MessageBox.Show(Customer.GetStringValue("Name"));
>	}
>}
>
>// Runtime extensible business object
>public class Customer : EntityBase<Customer> {
>	string id;
>
>	public string Id {
>		get {
>			return id;
>		}
>		set {
>			id = value;
>		}
>	}
>}
>
>// from core library
>public abstract class EntityBase<T> : Bag {
>	public virtual void SetValue(string propertyName, string propertyValue) {
>		PropertyDescriptor p = TypeDescriptor.GetProperties(typeof(T))[propertyName];
>		ITypeDescriptorContext ctx = new SimpleContext(this, p);
>		object val;
>		val = p.Converter.ConvertFromString(ctx, propertyValue);
>		p.SetValue(this, val);
>	}
>
>	public virtual string GetStringValue(string propertyName) {
>		PropertyDescriptor p = TypeDescriptor.GetProperties(typeof(T))[propertyName];
>		return p.GetValue(this).ToString();
>	}
>}
>
>interface IBag {
>	void OnAfterValueChanged(string propertyName);
>	void AddHandler(object key, EventHandler value);
>	void RemoveHandler(object key, EventHandler value);
>	void OnEvent(object key);
>	IBagValue GetValue(string propertyName);
>}
>
>interface IBagValue {
>	void ResetValue();
>	bool IsDefaultValue { get;}
>	object Value { get; set;}
>	event EventHandler ValueChanged;
>}
>
>interface IBagDefinition {
>	IBagValue Create(IBag bag);
>	PropertyDescriptor Property { get;}
>}
>
>sealed class BagDefinition<T> : IBagDefinition {
>	private readonly PropertyDescriptor property;
>	public PropertyDescriptor Property { get { return property; } }
>	private readonly T defaultValue;
>	public T DefaultValue { get { return defaultValue; } }
>	public string Name { get { return Property.Name; } }
>
>	IBagValue IBagDefinition.Create(IBag bag) {
>		return new BagValue<T>(bag, this);
>	}
>
>	public BagDefinition(string propertyName, Attribute[] attributes) {
>		defaultValue = default(T);
>		if (attributes != null) { // check for a default value
>			foreach (Attribute attrib in attributes) {
>				DefaultValueAttribute defAttrib = attrib as
>DefaultValueAttribute;
>				if (defAttrib != null) {
>					defaultValue = (T)defAttrib.Value;
>					break;
>				}
>			}
>		}
>		property = new BagPropertyDescriptor(propertyName, attributes);
>	}
>
>
>	internal class BagPropertyDescriptor : PropertyDescriptor {
>		public BagPropertyDescriptor(string name, Attribute[] attributes)
>			: base(name, attributes) { }
>
>
>		private IBagValue GetBagValue(object component) {
>			return ((IBag)component).GetValue(Name);
>		}
>
>
>		public override object GetValue(object component) {
>			return GetBagValue(component).Value;
>		}
>
>
>		public override void SetValue(object component, object value) {
>			GetBagValue(component).Value = value;
>		}
>
>
>		public override Type ComponentType {
>			get { return typeof(Bag); }
>		}
>
>
>		public override Type PropertyType {
>			get { return typeof(T); }
>		}
>
>
>		public override bool IsReadOnly {
>			get { return false; }
>		}
>
>
>		public override bool CanResetValue(object component) {
>			return true;
>		}
>
>
>		public override void ResetValue(object component) {
>			GetBagValue(component).ResetValue();
>		}
>
>
>		public override bool ShouldSerializeValue(object component) {
>			return !GetBagValue(component).IsDefaultValue;
>		}
>		public override bool SupportsChangeEvents {
>			get { return true; }
>		}
>
>
>		public override void AddValueChanged(object component,
>EventHandler handler) {
>			GetBagValue(component).ValueChanged += handler;
>		}
>
>		public override void RemoveValueChanged(object component,
>																EventHandler handler) {
>			GetBagValue(component).ValueChanged -= handler;
>		}
>	}
>}
>
>
>sealed class BagValue<T> : IBagValue, ITypeDescriptorContext {
>	private T value;
>	private readonly IBag bag;
>	void IBagValue.ResetValue() {
>		Value = Definition.DefaultValue;
>	}
>	bool IBagValue.IsDefaultValue {
>		get {
>			return EqualityComparer<T>.Default.Equals(Value,
>																	Definition.DefaultValue);
>		}
>	}
>	private readonly BagDefinition<T> definition;
>	public IBag Bag { get { return bag; } }
>	public BagDefinition<T> Definition { get { return definition; } }
>	public BagValue(IBag bag, BagDefinition<T> definition) {
>		if (bag == null) throw new ArgumentNullException("bag");
>		if (definition == null) throw new ArgumentNullException("definition");
>		this.bag = bag;
>		this.definition = definition;
>		Value = Definition.DefaultValue;
>	}
>
>	public T Value {
>		get { return value; }
>		set {
>			if (EqualityComparer<T>.Default.Equals(Value, value))
>				return;
>			this.value = value;
>			Bag.OnAfterValueChanged(Definition.Name);
>			Bag.OnEvent(Definition);
>		}
>	}
>
>
>	public event EventHandler ValueChanged {
>		add { Bag.AddHandler(Definition, value); }
>		remove { Bag.RemoveHandler(Definition, value); }
>	}
>
>
>	object IBagValue.Value {
>		get { return Value; }
>		set { Value = (T)value; }
>	}
>
>
>	IContainer ITypeDescriptorContext.Container {
>		get {
>			return null;
>		}
>	}
>	object ITypeDescriptorContext.Instance { get { return Bag; } }
>	void ITypeDescriptorContext.OnComponentChanged() {
>		Bag.OnAfterValueChanged(Definition.Name);
>	}
>	bool ITypeDescriptorContext.OnComponentChanging() { return true; }
>	PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor {
>		get { return Definition.Property; }
>	}
>	object IServiceProvider.GetService(Type serviceType) {
>		return null;
>	}
>}
>
>
>public /*sealed*/ class Bag : IBag, INotifyPropertyChanged {
>
>	private EventHandlerList events;
>	void IBag.AddHandler(object key, EventHandler handler) {
>		AddHandler(key, handler);
>	}
>	void IBag.RemoveHandler(object key, EventHandler handler) {
>		RemoveHandler(key, handler);
>	}
>	void IBag.OnEvent(object key) {
>		OnEvent(key);
>	}
>	private void AddHandler(object key, Delegate handler) {
>		if (handler == null) return;
>		if (events == null) events = new EventHandlerList();
>		events.AddHandler(key, handler);
>	}
>	private void RemoveHandler(object key, Delegate handler) {
>		if (events == null || handler == null) return;
>		events.RemoveHandler(key, handler);
>	}
>	private void OnEvent(object key) {
>		if (events == null) return;
>		EventHandler handler = events[key] as EventHandler;
>		if (handler != null) handler(this, EventArgs.Empty);
>	}
>	public event PropertyChangedEventHandler PropertyChanged {
>		add { AddHandler(EVENT_PropertyChanged, value); }
>		remove { RemoveHandler(EVENT_PropertyChanged, value); }
>	}
>	private static readonly object EVENT_PropertyChanged = new object();
>	private void OnPropertyChanged(string propertyName) {
>		if (events == null) return;
>		PropertyChangedEventHandler handler = events[EVENT_PropertyChanged] as
>PropertyChangedEventHandler;
>		if (handler != null) handler(this, new
>PropertyChangedEventArgs(propertyName));
>	}
>
>
>	void IBag.OnAfterValueChanged(string propertyName) {
>		OnPropertyChanged(propertyName);
>	}
>
>
>	IBagValue IBag.GetValue(string propertyName) {
>		return GetValue(propertyName);
>	}
>
>
>	private readonly Dictionary<string, IBagValue> values =
>			new Dictionary<string, IBagValue>(StringComparer.InvariantCulture);
>
>
>	private IBagValue GetValue(string propertyName) {
>		lock (values) {
>			IBagValue value;
>			if (!values.TryGetValue(propertyName, out value)) {
>				value = CreateValue(this, propertyName);
>				values.Add(propertyName, value);
>			}
>			return value;
>		}
>	}
>
>
>	static readonly Dictionary<string, IBagDefinition> defintions =
>			new Dictionary<string,
>IBagDefinition>(StringComparer.InvariantCulture);
>
>
>	public static PropertyDescriptor AddProperty<T>(string propertyName,
>params Attribute[] attributes) {
>		BagDefinition<T> def = new BagDefinition<T>(propertyName, attributes);
>		lock (defintions) {
>			defintions.Add(propertyName, def);
>			BagDescriptionProvider.ResetProperties();
>		}
>		return def.Property;
>	}
>
>
>	internal static PropertyDescriptorCollection GetProperties() {
>		lock (defintions) {
>			PropertyDescriptor[] props = new PropertyDescriptor[defintions.Count];
>			int i = 0;
>			foreach (IBagDefinition def in defintions.Values) {
>				props[i++] = def.Property;
>			}
>			return new PhantomPropertyDescriptorCollection(props, false);
>		}
>	}
>
>
>	internal sealed class PhantomPropertyDescriptorCollection :
>PropertyDescriptorCollection {
>
>
>		public PhantomPropertyDescriptorCollection(PropertyDescriptor[]
>properties, bool readOnly)
>			: base(properties, readOnly) {
>		}
>
>
>		public override PropertyDescriptor Find(string name, bool ignoreCase) {
>			PropertyDescriptor prop = base.Find(name, ignoreCase);
>			if (prop == null) {
>				prop = AddProperty<object>(name);
>				Add(prop);
>			}
>			return prop;
>		}
>	}
>
>
>	static IBagValue CreateValue(IBag bag, string propertyName) {
>		lock (defintions) {
>			return defintions[propertyName].Create(bag);
>		}
>	}
>
>
>	public Bag() { }
>
>	static Bag() {
>		BagDescriptionProvider.Initialize();
>	}
>}
>
>
>sealed class BagDescriptionProvider : TypeDescriptionProvider {
>	static readonly BagTypeDescriptor descriptor;
>
>	[MethodImpl(MethodImplOptions.NoInlining)]
>	internal static void Initialize() { } // to force static ctor
>	static BagDescriptionProvider() {
>		ICustomTypeDescriptor parent =
>TypeDescriptor.GetProvider(typeof(Bag)).GetTypeDescriptor(typeof(Bag));
>		descriptor = new BagTypeDescriptor(parent);
>		TypeDescriptor.AddProvider(new BagDescriptionProvider(), typeof(Bag));
>	}
>	public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
>object instance) {
>		return descriptor;
>	}
>
>
>	internal static void ResetProperties() {
>		descriptor.ResetProperties();
>	}
>}
>
>
>sealed class BagTypeDescriptor : CustomTypeDescriptor {
>	public BagTypeDescriptor(ICustomTypeDescriptor parent)
>		: base(parent) {
>		if (parent == null) throw new ArgumentNullException("parent");
>	}
>	private PropertyDescriptorCollection properties;
>	internal void ResetProperties() {
>		properties = null;
>	}
>	public override PropertyDescriptorCollection GetProperties(Attribute[]
>attributes) {
>		return GetProperties();
>	}
>	public override PropertyDescriptorCollection GetProperties() {
>		if (properties == null) {
>			properties = Bag.GetProperties();
>		}
>		return properties;
>	}
>}
>
>
>
>
>[ImmutableObject(true)]
>class SimpleContext : ITypeDescriptorContext {
>	readonly object instance;
>	readonly PropertyDescriptor property;
>
>	internal SimpleContext(object instance, PropertyDescriptor
>														property) {
>		this.instance = instance;
>		this.property = property;
>	}
>
>	public IContainer Container { get { return null; } }
>	public object Instance { get { return instance; } }
>	public void OnComponentChanged() { }
>	public bool OnComponentChanging() { return true; }
>
>	public PropertyDescriptor PropertyDescriptor {
>		get {
>			return property;
>		}
>	}
>
>	public object GetService(Type serviceType) { return null; }
>}
>
>>Thank you Andrus. It's going to take me a while to try your code, but it will be very educational.
Pertti Karjalainen
Product Manager
Northern Lights Software
Fairfax, CA USA
www.northernlightssoftware.com
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform