可以将动态对象转换为 ExpandoObject (c#)
can one convert a dynamic object to an ExpandoObject (c#)
我正在从驱动程序 api(在 dll 中)获取类型 "Sealed Class" 的动态对象。我想用一些额外的属性来装饰这个对象。
我想做一些事情:
public void expandIT(dynamic sealedObject) {
ExpandoObject expand = new ExpandoObject(sealedObject);
expand.time = DateTime.Now();
etc....
}
更新
我喜欢 JCL 的解决方案。但是对于我想做的事情,创建一个 ExpandoObject 然后将动态密封 class 对象作为子对象 属性 嵌入,然后将我的属性添加到父 ExpandoObject 更容易。感谢 JCL,对于如何执行此操作,我的大脑处于冻结状态。
我
没有。 dynamic
对象不会在编译时强制执行类型,但它不会神奇地使您的对象可扩展(除非它是 ExpandoObject
)。
但是,您可以使用 DynamicObject
制作某种包装器或代理...类似于:
public class ExpandedObjectFromApi : DynamicObject
{
private Dictionary<string, object> _customProperties = new Dictionary<string, object>();
private object _currentObject;
public ExpandedObjectFromApi(dynamic sealedObject)
{
_currentObject = sealedObject;
}
private PropertyInfo GetPropertyInfo(string propertyName)
{
return _currentObject.GetType().GetProperty(propertyName);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var prop = GetPropertyInfo(binder.Name);
if(prop != null)
{
result = prop.GetValue(_currentObject);
return true;
}
result = _customProperties[binder.Name];
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var prop = GetPropertyInfo(binder.Name);
if(prop != null)
{
prop.SetValue(_currentObject, value);
return true;
}
if(_customProperties.ContainsKey(binder.Name))
_customProperties[binder.Name] = value;
else
_customProperties.Add(binder.Name, value);
return true;
}
}
然后你可以像这样使用它:
dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject);
这应该 return 如果找到原始对象属性,或者如果在原始对象中没有 属性 该名称,它会将其添加为 "custom" 属性.
我在 Stack Overflow 编辑器中编写了代码,可能犯了很多错误,它不适合 copy/paste,并且需要大量的错误检查(还需要实现字段和方法,如果接收到的对象有它们)。刚刚写的,所以你得到了基本的想法。
您可能还想添加一个特殊的 属性(例如称为 WrappedObject
的东西)并将其捕获到 TryGetMember
,这样您就可以取回原始对象。
string json = JsonConvert.Serialize(dynamicObject);
ExpandoObject eo = JsonConvert.Deserialize<ExpandoObject>(json);
帮助我将 dynamic
更改为 ExpandoObject
。
我正在从驱动程序 api(在 dll 中)获取类型 "Sealed Class" 的动态对象。我想用一些额外的属性来装饰这个对象。
我想做一些事情:
public void expandIT(dynamic sealedObject) {
ExpandoObject expand = new ExpandoObject(sealedObject);
expand.time = DateTime.Now();
etc....
}
更新
我喜欢 JCL 的解决方案。但是对于我想做的事情,创建一个 ExpandoObject 然后将动态密封 class 对象作为子对象 属性 嵌入,然后将我的属性添加到父 ExpandoObject 更容易。感谢 JCL,对于如何执行此操作,我的大脑处于冻结状态。 我
没有。 dynamic
对象不会在编译时强制执行类型,但它不会神奇地使您的对象可扩展(除非它是 ExpandoObject
)。
但是,您可以使用 DynamicObject
制作某种包装器或代理...类似于:
public class ExpandedObjectFromApi : DynamicObject
{
private Dictionary<string, object> _customProperties = new Dictionary<string, object>();
private object _currentObject;
public ExpandedObjectFromApi(dynamic sealedObject)
{
_currentObject = sealedObject;
}
private PropertyInfo GetPropertyInfo(string propertyName)
{
return _currentObject.GetType().GetProperty(propertyName);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var prop = GetPropertyInfo(binder.Name);
if(prop != null)
{
result = prop.GetValue(_currentObject);
return true;
}
result = _customProperties[binder.Name];
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var prop = GetPropertyInfo(binder.Name);
if(prop != null)
{
prop.SetValue(_currentObject, value);
return true;
}
if(_customProperties.ContainsKey(binder.Name))
_customProperties[binder.Name] = value;
else
_customProperties.Add(binder.Name, value);
return true;
}
}
然后你可以像这样使用它:
dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject);
这应该 return 如果找到原始对象属性,或者如果在原始对象中没有 属性 该名称,它会将其添加为 "custom" 属性.
我在 Stack Overflow 编辑器中编写了代码,可能犯了很多错误,它不适合 copy/paste,并且需要大量的错误检查(还需要实现字段和方法,如果接收到的对象有它们)。刚刚写的,所以你得到了基本的想法。
您可能还想添加一个特殊的 属性(例如称为 WrappedObject
的东西)并将其捕获到 TryGetMember
,这样您就可以取回原始对象。
string json = JsonConvert.Serialize(dynamicObject);
ExpandoObject eo = JsonConvert.Deserialize<ExpandoObject>(json);
帮助我将 dynamic
更改为 ExpandoObject
。