gpt4 book ai didi

c# - 使用 propertyBuilder 在运行时向现有对象添加属性

转载 作者:行者123 更新时间:2023-12-02 22:22:14 27 4
gpt4 key购买 nike

一个对象有一些属性,现在在运行时——当满足一个条件时。我想给这个对象添加新的属性。

不能使用“DynamicObject”,因为我不会事先知道属性名称

我来到了 PropertyBuilder http://msdn.microsoft.com/en-us/library/system.reflection.emit.propertybuilder.aspx

但我找不到有关如何使用 propertBuilder 将属性添加到已定义的现有类的现有对象的帮助。

最佳答案

您不能在运行时向对象或类型添加真实(反射)属性。

如果此处的上下文是数据绑定(bind),那么您可以通过实现 ICustomTypeDescriptorTypeDescriptionProvider 中的一个或多个来实现所有人工属性, TypeConverterITypedList - 并为额外的属性提供您自己的 PropertyDescriptor

  • ICustomTypeDescriptor 是每个对象并绑定(bind)到该对象
  • TypeDescriptionProvider 是按对象或按类型的,并且与对象分开
  • TypeConverter 是针对每个类型的,特别是被 PropertyGrid
  • 使用
  • ITypedList 被列表(IList)用来描述子对象的属性

例子:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
FooConverter.AddProperty("Time", typeof(DateTime));
FooConverter.AddProperty("Age", typeof(int));
using (var grid = new PropertyGrid { Dock = DockStyle.Fill, SelectedObject = new Foo() })
using (var form = new Form { Controls = { grid } })
{
Application.Run(form);
}
}
}
class FooConverter : ExpandableObjectConverter
{
private static readonly List<Tuple<string, Type>> customProps = new List<Tuple<string, Type>>();
public static void AddProperty(string name, Type type)
{
lock (customProps) customProps.Add(Tuple.Create(name, type));
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, System.Attribute[] attributes)
{
var orig = base.GetProperties(context, value, attributes);
lock(customProps)
{
if(customProps.Count == 0) return orig;

PropertyDescriptor[] props = new PropertyDescriptor[orig.Count + customProps.Count];
orig.CopyTo(props, 0);
int i = orig.Count;
foreach (var prop in customProps)
{
props[i++] = new SimpleDescriptor(prop.Item1, prop.Item2);
}
return new PropertyDescriptorCollection(props);
}
}
class SimpleDescriptor : PropertyDescriptor
{
private readonly Type type;
public SimpleDescriptor(string name, Type type)
: base(name, new Attribute[0])
{
this.type = type;
}
public override Type PropertyType { get { return type;} }
public override bool SupportsChangeEvents { get { return false; } }
public override void ResetValue(object component) { SetValue(component, null); }
public override bool CanResetValue(object component) { return true; }
public override bool ShouldSerializeValue(object component) { return GetValue(component) != null; }
public override bool IsReadOnly { get { return false; } }
public override Type ComponentType { get { return typeof(Foo); } }
public override object GetValue(object component) { return ((Foo)component).GetExtraValue(Name); }
public override void SetValue(object component, object value) { ((Foo)component).SetExtraValue(Name, value); }
public override string Category { get { return "Extra values"; } }
}
}
[TypeConverter(typeof(FooConverter))]
public class Foo
{
Dictionary<string, object> extraValues;
internal object GetExtraValue(string name)
{
object value;
if (extraValues == null || !extraValues.TryGetValue(name, out value)) value = null;
return value;
}
internal void SetExtraValue(string name, object value)
{
if (extraValues == null && value != null) extraValues = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
if (value == null) extraValues.Remove(name);
else extraValues[name] = value;
}
public int Id { get; set; }
public string Name { get; set; }
}

关于c# - 使用 propertyBuilder 在运行时向现有对象添加属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13524426/

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