Pao*_*sco 57
你可以使用字典
Dictionary<string,object> properties;
Run Code Online (Sandbox Code Playgroud)
我认为在大多数情况下,类似的东西都是这样做的.
在任何情况下,你都不会从使用set和get访问器创建"真实"属性中获得任何东西,因为它只会在运行时创建,而你不会在代码中使用它...
这是一个示例,显示了过滤和排序的可能实现(无错误检查):
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1 {
class ObjectWithProperties {
Dictionary<string, object> properties = new Dictionary<string,object>();
public object this[string name] {
get {
if (properties.ContainsKey(name)){
return properties[name];
}
return null;
}
set {
properties[name] = value;
}
}
}
class Comparer<T> : IComparer<ObjectWithProperties> where T : IComparable {
string m_attributeName;
public Comparer(string attributeName){
m_attributeName = attributeName;
}
public int Compare(ObjectWithProperties x, ObjectWithProperties y) {
return ((T)x[m_attributeName]).CompareTo((T)y[m_attributeName]);
}
}
class Program {
static void Main(string[] args) {
// create some objects and fill a list
var obj1 = new ObjectWithProperties();
obj1["test"] = 100;
var obj2 = new ObjectWithProperties();
obj2["test"] = 200;
var obj3 = new ObjectWithProperties();
obj3["test"] = 150;
var objects = new List<ObjectWithProperties>(new ObjectWithProperties[]{ obj1, obj2, obj3 });
// filtering:
Console.WriteLine("Filtering:");
var filtered = from obj in objects
where (int)obj["test"] >= 150
select obj;
foreach (var obj in filtered){
Console.WriteLine(obj["test"]);
}
// sorting:
Console.WriteLine("Sorting:");
Comparer<int> c = new Comparer<int>("test");
objects.Sort(c);
foreach (var obj in objects) {
Console.WriteLine(obj["test"]);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 30
如果您需要这个用于数据绑定目的,可以使用自定义描述符模型执行此操作...通过实现ICustomTypeDescriptor,TypeDescriptionProvider和/或TypeCoverter,您可以PropertyDescriptor在运行时创建自己的实例.这是控制像DataGridView,PropertyGrid等用于显示性能.
要绑定到列表,您需要ITypedList和IList; 用于基本排序:IBindingList; 用于过滤和高级排序:IBindingListView; 对于完整的"新行"支持(DataGridView):( ICancelAddNewp!).
虽然这是很多工作.DataTable(虽然我讨厌它)是做同样事情的廉价方式.如果您不需要数据绑定,只需使用哈希表;-p
这是一个简单的例子 - 但你可以做更多......
Alu*_*ord 12
我不确定你真的想做你想做的事,但我不能理解为什么!
在JIT之后,您无法向类中添加属性.
您可以获得的最接近的是使用Reflection.Emit动态创建子类型并复制现有字段,但您必须自己更新对该对象的所有引用.
您也无法在编译时访问这些属性.
就像是:
public class Dynamic
{
public Dynamic Add<T>(string key, T value)
{
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Dynamic.dll");
TypeBuilder typeBuilder = moduleBuilder.DefineType(Guid.NewGuid().ToString());
typeBuilder.SetParent(this.GetType());
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(key, PropertyAttributes.None, typeof(T), Type.EmptyTypes);
MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + key, MethodAttributes.Public, CallingConventions.HasThis, typeof(T), Type.EmptyTypes);
ILGenerator getter = getMethodBuilder.GetILGenerator();
getter.Emit(OpCodes.Ldarg_0);
getter.Emit(OpCodes.Ldstr, key);
getter.Emit(OpCodes.Callvirt, typeof(Dynamic).GetMethod("Get", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(typeof(T)));
getter.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getMethodBuilder);
Type type = typeBuilder.CreateType();
Dynamic child = (Dynamic)Activator.CreateInstance(type);
child.dictionary = this.dictionary;
dictionary.Add(key, value);
return child;
}
protected T Get<T>(string key)
{
return (T)dictionary[key];
}
private Dictionary<string, object> dictionary = new Dictionary<string,object>();
}
Run Code Online (Sandbox Code Playgroud)
我没有在这台机器上安装VS,所以让我知道是否有任何大规模的错误(好吧......除了大量的性能问题,但我没有编写规范!)
现在你可以使用它:
Dynamic d = new Dynamic();
d = d.Add("MyProperty", 42);
Console.WriteLine(d.GetType().GetProperty("MyProperty").GetValue(d, null));
Run Code Online (Sandbox Code Playgroud)
您也可以像支持后期绑定的语言中的普通属性一样使用它(例如,VB.NET)
| 归档时间: |
|
| 查看次数: |
128425 次 |
| 最近记录: |