我是这样的A类:
public class A
{
private String id; // Generated on server
private DateTime timestamp;
private int trash;
private Humanity.FeedTypeEnum feedType
private List<Property> properties;
// ...
其中Property
是:
public class Property
{
private Humanity.PropertyTypeEnum type;
private string key;
private object value;
//...
我想构建一个动态对象,将List<Property> properties
A字段与原始属性相对应。例如:
A a = new A();
a.Id = "Id";
a.Timestamp = DateTime.Now;
a.Trash = 2;
a.FeedType = Humanity.FeedTypeEnum.Mail;
a.Properties = new List<Property>()
{
new Property()
{
Type = Humanity.PropertyTypeEnum.String,
Key = "name"
Value = "file1.pdf"
},
new Property()
{
Type = Humanity.PropertyTypeEnum.Timestamp,
Key = "creationDate",
Value = Datetime.Now
}
}
正如我所评论的那样,我想平放这个a
对象,以便访问这些属性:
String name = a.Name;
DateTime creationDate = a.CreationDate;
a.Name = "otherName";
a.CreationDate = creationDate.AddDays(1);
我使用Reflection实现了这一点。但是,我发现使用ExpandoObject
是最佳选择。
问题是,我怎样才能使用ExpandoObject
类?
答案 0 :(得分:2)
你可以做你想要的扩展DynamicObject
类:
class A : System.Dynamic.DynamicObject
{
// Other members
public List<Property> properties;
private readonly Dictionary<string, object> _membersDict = new Dictionary<string, object>();
public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
{
result = null;
if (!_membersDict.ContainsKey(binder.Name))
return false;
result = _membersDict[binder.Name];
return true;
}
public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value)
{
if (!_membersDict.ContainsKey(binder.Name))
return false;
_membersDict[binder.Name] = value;
return true;
}
public void CreateProperties()
{
foreach (Property prop in properties)
{
if (!_membersDict.ContainsKey(prop.key))
{
_membersDict.Add(prop.key, prop.value);
}
}
}
}
然后像这样使用它:
A a = new A();
/////////
a.Properties = new List<Property>()
{
new Property()
{
Type = Humanity.PropertyTypeEnum.String, // Now this property is useless, the value field has already a type, if you want you can add some logic around with this property to ensure that value will always be the same type
Key = "name"
Value = "file1.pdf"
},
new Property()
{
Type = Humanity.PropertyTypeEnum.Timestamp,
Key = "creationDate",
Value = Datetime.Now
}
}
a.CreateProperties();
dynamic dynA = a;
dynA.name = "value1";
答案 1 :(得分:1)
此方法只是覆盖方括号运算符。不像你想要的那样光滑,但更简单,更实用。 你绝对不能像你描述的那样拥有设计时间(当你编写代码时)。 您可以在运行时使其与反射一起工作,但肯定不是您表现出来的方式吗?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
A a = new A();
a.properties = new List<Property>()
{
new Property(Humanity.PropertyTypeEnum.String, "name", "file1.pdf"),
new Property(Humanity.PropertyTypeEnum.Timestamp, "creationDate", DateTime.Now)
};
//String name = a.Name;
//DateTime creationDate = a.CreationDate;
//a.Name = "otherName";
//a.CreationDate = creationDate.AddDays(1);
String name = (String)a["name"];
DateTime creationDate = (DateTime)a["creationDate"];
a["name"] = "otherName";
a["creationDate"] = creationDate.AddDays(1);
}
public class A
{
private Dictionary<Property, object> myvalues = new Dictionary<Property, object>();
public List<Property> properties;
public object this[string name]
{
get
{
var prop = properties.Find(p => p.key == name);
if (prop == null)
throw new Exception("property " + name + " not found.");
return prop.value;
}
set
{
var prop = properties.Find(p => p.key == name);
if (prop == null)
throw new Exception("property " + name + " not found.");
prop.value = value;
}
}
}
public class Property
{
public Property(Humanity.PropertyTypeEnum type, string key, object value) { this.type = type; this.key = key; this.value = value; }
private Humanity.PropertyTypeEnum type;
public string key;
public object value;
}
}
}
namespace Humanity
{
public enum PropertyTypeEnum { String, Timestamp };
public enum FeedTypeEnum { };
}