gpt4 book ai didi

.net - ICustomTypeDescriptor 对象的包装器

转载 作者:行者123 更新时间:2023-12-02 21:13:12 25 4
gpt4 key购买 nike

我在应用程序中实现了 ICustomTypeDescriptor,以便能够在运行时定义自定义属性。我的基本实现如下:

public class DynamicClass <T> : ICustomTypeDescriptor
{
private readonly T _object;

public DynamicClass(T trackedObject)
{
_object = trackedObject;
}

// Collection to code add dynamic properties
public KeyedCollection<string, DynamicProperty> Properties
{
get;
private set;
}

// ICustomTypeDescriptor implementation
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(_object, true);
}

public string GetClassName()
{
return TypeDescriptor.GetClassName(_object, true);
}

public string GetComponentName()
{
return TypeDescriptor.GetComponentName(_object, true);
}

public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(_object, true);
}

public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(_object, true);
}

public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(_object, true);
}

public object GetEditor(Type editorBaseType)
{
throw new NotImplementedException();
}

public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents(_object, true);
}

public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(_object, attributes, true);
}

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return TypeDescriptor.GetProperties(_object, true);
}

public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return TypeDescriptor.GetProperties(_object, attributes, true);
}

public object GetPropertyOwner(PropertyDescriptor pd)
{
return _object;
}
}

问题是,现在当我使用 DynamicClass 绑定(bind)器将对象绑定(bind)到文本框时,它不再起作用。

我这样使用它:

 DynamicClass<ExtensionModel> binder = new DynamicClass<ExtensionModel>(ext);
_versionLabel.DataBindings.Add("Text", binder, "SelectedVersion", false, DataSourceUpdateMode.OnPropertyChanged);

我得到了异常:“对象与目标类型不匹配。”

Object does not match target type.

at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.ComponentModel.ReflectEventDescriptor.AddEventHandler(Object component, Delegate value) at System.ComponentModel.ReflectPropertyDescriptor.AddValueChanged(Object component, EventHandler handler) at System.Windows.Forms.BindToObject.CheckBinding() at System.Windows.Forms.Binding.SetListManager(BindingManagerBase bindingManagerBase) at System.Windows.Forms.ListManagerBindingsCollection.AddCore(Binding dataBinding) at System.Windows.Forms.BindingsCollection.Add(Binding binding) at System.Windows.Forms.BindingContext.UpdateBinding(BindingContext newBindingContext, Binding binding) at System.Windows.Forms.Control.UpdateBindings()

如果我使用 ext 对象而不是绑定(bind)器,则绑定(bind)有效。我是否错过了 ICustomTypeDescriptor 实现中的某些内容?

最佳答案

您必须用自定义描述符包装原始描述符。这是代码:

#region IBindingProxy

public interface IBindingProxy
{
void CheckAndNotify();
}

#endregion

public class BindingProxy : CustomTypeDescriptor, INotifyPropertyChanged, IBindingProxy
{
#region Static Constructor

private static readonly IDictionary<Type, PropertyDescriptorCollection> propertyCache;

static BindingProxy()
{
propertyCache = new Dictionary<Type, PropertyDescriptorCollection>();
}

private static PropertyDescriptorCollection GetTypeProperties(Type type)
{
lock (propertyCache)
{
PropertyDescriptorCollection properties;
if (!propertyCache.TryGetValue(type, out properties))
{
var list = new List<PropertyDescriptor>();
GetTypeProperties(list, type);
properties = new PropertyDescriptorCollection(list.ToArray());
propertyCache.Add(type, properties);
}
return properties;
}
}

private static void GetTypeProperties(ICollection<PropertyDescriptor> list, Type type)
{
foreach (var @interface in type.GetInterfaces())
{
GetTypeProperties(list, @interface);
}
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(type))
{
list.Add(new ProxyPropertyDescriptor(property));
}
}

#endregion

private readonly PropertyDescriptorCollection properties;
private readonly object instance;

public event PropertyChangedEventHandler PropertyChanged;

public BindingProxy(object instance)
{
this.instance = instance;

properties = instance == null
? PropertyDescriptorCollection .Empty
: GetTypeProperties(instance.GetType());
}

public void CheckAndNotify()
{
OnPropertyChanged(null);
}

protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}

public object Instance
{
get { return instance; }
}

public override PropertyDescriptorCollection GetProperties()
{
return GetProperties(null);
}

public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return properties;
}

public override Object GetPropertyOwner(PropertyDescriptor property)
{
return this;
}

#region ProxyPropertyDescriptor

private class ProxyPropertyDescriptor : PropertyDescriptor
{
private readonly PropertyDescriptor property;

public ProxyPropertyDescriptor(PropertyDescriptor property) : base(property)
{
this.property = property;
}

//public override string DisplayName
//{
// get { return property.DisplayName; }
//}

//public override string Description
//{
// get { return property.Description; }
//}

//public override string Category
//{
// get { return property.Category; }
//}

//public override TypeConverter Converter
//{
// get { return converter; }
//}

public override bool IsReadOnly
{
get { return property.IsReadOnly; }
}

public override void ResetValue(object component)
{
}

public override bool CanResetValue(object component)
{
return false;
}

public override bool ShouldSerializeValue(object component)
{
return false;
}

public override Type ComponentType
{
get { return property.ComponentType; }
}

public override Type PropertyType
{
get { return property.PropertyType; }
}

public override object GetValue(object component)
{
return property.GetValue(((BindingProxy)component).instance);
}

public override void SetValue(object component, object value)
{
var instance = ((BindingProxy)component).instance;
property.SetValue(instance, value);
OnValueChanged(instance, EventArgs.Empty);
}
}

#endregion
}

关于.net - ICustomTypeDescriptor 对象的包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9427587/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com