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

回到顶部