我知道有一些问题可以解决这个问题,但答案通常是推荐字典或参数集合,这在我的情况下不起作用。
我正在使用一个通过反射工作的库,可以对具有属性的对象执行许多巧妙的操作。 这适用于已定义的类以及动态类。 我需要更进一步并按照以下方式做一些事情:
public static object GetDynamicObject(Dictionary<string,object> properties) {
var myObject = new object();
foreach (var property in properties) {
//This next line obviously doesn't work...
myObject.AddProperty(property.Key,property.Value);
}
return myObject;
}
public void Main() {
var properties = new Dictionary<string,object>();
properties.Add("Property1",aCustomClassInstance);
properties.Add("Property2","TestString2");
var myObject = GetDynamicObject(properties);
//Then use them like this (or rather the plug in uses them through reflection)
var customClass = myObject.Property1;
var myString = myObject.Property2;
}
该库可以很好地处理动态变量类型,并手动分配属性。 但我不知道会预先添加多少或哪些属性。
您看过 ExpandoObject 吗?
参见:https://learn.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject
来自 MSDN:
ExpandoObject 类使您能够在运行时添加和删除其实例的成员,以及设置和获取这些成员的值。此类支持动态绑定,这使您能够使用标准语法(如sampleObject.sampleMember),而不是更复杂的语法(如sampleObject.GetAttribute(“sampleMember”))。
让您可以做一些很酷的事情,例如:
dynamic dynObject = new ExpandoObject();
dynObject.SomeDynamicProperty = "Hello!";
dynObject.SomeDynamicAction = (msg) =>
{
Console.WriteLine(msg);
};
dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);
根据您的实际代码,您可能更感兴趣:
public static dynamic GetDynamicObject(Dictionary<string, object> properties)
{
return new MyDynObject(properties);
}
public sealed class MyDynObject : DynamicObject
{
private readonly Dictionary<string, object> _properties;
public MyDynObject(Dictionary<string, object> properties)
{
_properties = properties;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _properties.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_properties.ContainsKey(binder.Name))
{
result = _properties[binder.Name];
return true;
}
else
{
result = null;
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (_properties.ContainsKey(binder.Name))
{
_properties[binder.Name] = value;
return true;
}
else
{
return false;
}
}
}
这样你只需要:
var dyn = GetDynamicObject(new Dictionary<string, object>()
{
{"prop1", 12},
});
Console.WriteLine(dyn.prop1);
dyn.prop1 = 150;
从 DynamicObject 派生允许您提出自己的策略来处理这些动态成员请求,注意这里有怪物:编译器将不能能够验证大量动态调用,并且您不会得到智能感知,所以请记住这一点。
感谢@Clint 的精彩回答:
只是想强调使用 Expando 对象解决这个问题是多么容易:
var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
foreach (var property in properties) {
dynamicObject.Add(property.Key,property.Value);
}
您可以将 json 字符串反序列化为字典,然后添加新属性,然后将其序列化。
var jsonString = @"{}";
var jsonDoc = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);
jsonDoc.Add("Name", "Khurshid Ali");
Console.WriteLine(JsonSerializer.Serialize(jsonDoc));
这是@Clint 课程的精简版本。 您可以使用最初分配的公共 Dictionary 成员变量 Props,或者在外部构建您的 Dictionary 并在稍后的时间用它覆盖 Props Dictionary。
public class Expando : DynamicObject
{
public Dictionary<string, object?> Props = new Dictionary<string, object?>();
public override IEnumerable<string> GetDynamicMemberNames()
{
return Props.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object? result)
{
result = null;
Props.TryGetValue(binder.Name, out result);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object? value)
{
Props[binder.Name] = value;
return true;
}
}