C#动态类
我在说类似于dynamic
的东西。 This没有回答我的问题,所以这个问题。我想有一个可以在运行时添加属性的类。它需要从object
类型继承。C#动态类
我见过从DynamicObject
继承,但没有说明如何在运行时添加属性。对我来说,能否给我一些启示?
我有这样一个类:
public class SomeModel : DynamicObject { public string SomeMandatoryProperty {get; set;}
}
我想从另一个类在运行时添加的所有属性这一类。所以例如。
SomeModel m = new SomeModel(); m = someOtherClass;
string hi = m.otherClassProp; //Property from other class is added.
string mandatory = m.SomeMandatoryProperty; //From the mandatory property set previously.
回答:
你想使用的ExpandoObject
因为您可以根据需要动态地添加属性。然而,没有直接的方法可以很容易地用另一个对象的值填充实例。您必须使用反射手动添加它。
你想编写一个包装器对象,你可以添加属性,同时仍然访问内部?您可能想要这样认为,您不必在两个不同的对象实例之间管理两个值的副本。我编写了一个测试类来包装字符串对象,以演示如何做到这一点(类似于ExpandoObject
的工作原理)。它应该给你一个关于如何为你的类型做这件事的想法。
class DynamicString : DynamicObject {
static readonly Type strType = typeof(string);
private string instance;
private Dictionary<string, object> dynProperties;
public DynamicString(string instance)
{
this.instance = instance;
dynProperties = new Dictionary<string, object>();
}
public string GetPrefixString(string prefix)
{
return String.Concat(prefix, instance);
}
public string GetSuffixString(string suffix)
{
return String.Concat(instance, suffix);
}
public override string ToString()
{
return instance;
}
public override bool TryConvert(ConvertBinder binder, out object result)
{
if (binder.Type != typeof(string))
return base.TryConvert(binder, out result);
result = instance;
return true;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var method = strType.GetMethod(binder.Name, args.Select(a => a.GetType()).ToArray());
if (method == null)
{
result = null;
return false;
}
result = method.Invoke(instance, args);
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var members = strType.GetMember(binder.Name);
if (members.Length > 0)
{
var member = members.Single();
switch (member.MemberType)
{
case MemberTypes.Property:
result = ((PropertyInfo)member).GetValue(instance, null);
return true;
break;
case MemberTypes.Field:
result = ((FieldInfo)member).GetValue(instance);
return true;
break;
}
}
return dynProperties.TryGetValue(binder.Name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var ret = base.TrySetMember(binder, value);
if (ret) return true;
dynProperties[binder.Name] = value;
return true;
}
}
如果您想要冒险,可以定义自己的元对象来处理绑定。你可能会得到不同类型的可重用元对象,并极大地简化你的代码。我已经玩了一段时间了,到目前为止还有这个。它不处理动态添加属性。我不会再做这个工作,但我会把它留在这里作为参考。
class DynamicString : DynamicObject {
class DynamicStringMetaObject : DynamicMetaObject
{
public DynamicStringMetaObject(Expression parameter, object value)
: base(parameter, BindingRestrictions.Empty, value)
{
}
public override DynamicMetaObject BindConvert(ConvertBinder binder)
{
if (binder.Type == typeof(string))
{
var valueType = Value.GetType();
return new DynamicMetaObject(
Expression.MakeMemberAccess(
Expression.Convert(Expression, valueType),
valueType.GetProperty("Instance")),
BindingRestrictions.GetTypeRestriction(Expression, valueType));
}
return base.BindConvert(binder);
}
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
System.Diagnostics.Trace.WriteLine(String.Format("BindGetMember: {0}", binder.Name));
var valueType = Value.GetType();
var self = Expression.Convert(Expression, valueType);
var valueMembers = valueType.GetMember(binder.Name);
if (valueMembers.Length > 0)
{
return BindGetMember(self, valueMembers.Single());
}
var members = typeof(string).GetMember(binder.Name);
if (members.Length > 0)
{
var instance =
Expression.MakeMemberAccess(
self,
valueType.GetProperty("Instance"));
return BindGetMember(instance, members.Single());
}
return base.BindGetMember(binder);
}
private DynamicMetaObject BindGetMember(Expression instance, MemberInfo member)
{
return new DynamicMetaObject(
Expression.Convert(
Expression.MakeMemberAccess(instance, member),
typeof(object)),
BindingRestrictions.GetTypeRestriction(Expression, Value.GetType())
);
}
}
public string Instance { get; private set; }
public DynamicString(string instance)
{
Instance = instance;
}
public override DynamicMetaObject GetMetaObject(Expression parameter)
{
return new DynamicStringMetaObject(parameter, this);
}
public override string ToString()
{
return Instance;
}
public string GetPrefixString(string prefix)
{
return String.Concat(prefix, Instance);
}
public string GetSuffixString(string suffix)
{
return String.Concat(Instance, suffix);
}
}
回答:
您应该可以使用ExpandoObject
来代替。一个ExpandoObject
可以有成员加入或在运行时取下,如果你要转换为XML等
从MSDN文档中有非常好的支持:
dynamic employee, manager; employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
manager = new ExpandoObject();
manager.Name = "Allison Brown";
manager.Age = 42;
manager.TeamSize = 10;
回答:
我认为你正在寻找ExpandoObject:
ExpandoObject类使您可以在运行时 实例添加和删除其实例的成员,也可以设置 并获取这些成员的值。这个 类支持动态绑定,其中 使您能够使用标准语法 ,如sampleObject.sampleMember,而不是 的更复杂的语法,如 sampleObject.GetAttribute(“sampleMember”)。
dynamic manager; manager = new ExpandoObject();
manager.Name = "Allison Brown";
manager.Age = 42;
manager.TeamSize = 10;
以上是 C#动态类 的全部内容, 来源链接: utcz.com/qa/263407.html