我有一个具有任意数量属性的ExpandoObject.我想将这些属性作为BsonDocument保存到MongoDB数据库.我尝试使用以下代码执行此操作:
private BsonDocument GetPlayerDocument(IPlayer player)
{
var ret = new BsonDocument();
ret.Add("FirstName", player.FirstName).
Add("LastName", player.LastName).
Add("Team", player.Team).
Add("Positions", new BsonArray(player.Positions));
foreach (var stat in (IDictionary<String, Object>)player.Stats)
{
ret.Add(stat.Key, stat.Value.ToBson());
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
但是,在对象上调用扩展方法ToBson()时,我收到以下异常:当State为:Initial时,不能调用WriteInt32.
我所知道的唯一的WrtieInt32是Marshall类的静态方法.我接近这个错吗?
我正在尝试使用ExpandoObject作为PropertyGrid的SelectedObject.我知道如何将我想要的属性添加到ExpandoObject:
public dynamic MakePropertyObject()
{
dynamic expando = new ExpandoObject();
var dictionary = expando as IDictionary<string, object>;
foreach(MyClass m in PropertiesINeedToAdd)
dictionary[m.Name] = m.Value;
return expando;
}
Run Code Online (Sandbox Code Playgroud)
此代码工作正常 - 调试器expando按预期显示属性的名称和值.
然而,没有生成的属性被显示出来PropertyGrid中的当我设置的返回值MakePropertyObject()到它的SelectedObject属性.我认为(也许是错误地),这是因为ExpandoObject的属性没有任何DisplayNameAttribute,DescriptionAttribute或任何用于控制其他属性如何属性显示在一个PropertyGrid.
我做了一些阅读和一些谷歌搜索,我无法弄清楚是否有一种方法来装饰ExpandoObject自定义属性的生成属性.有谁知道如何做到这一点,或者更好的方式来展示ExpandoObject一个PropertyGrid?
解:
@Stephen Cleary提供的答案是正确和有用的(谢谢,斯蒂芬).对于有同样问题的其他人来说,实施ICustomTypeDescriptor对我来说非常合适.
作为旁注,实现的对象ICustomTypeDescriptor为自身提供属性和事件描述符,而不是为另一个对象提供.我认为描述符和描述的内容应该首先通过属性或某种东西相关联 - 对我来说,一个对象应该描述它自己的类型似乎令人困惑和多余,但这确实是如何PropertyGrid使用ICustomTypeDescriptor接口的.
目前我使用ExpandoObject动态存储名字和姓氏.
例如
// Create Expando object for testing
dynamic employee = new ExpandoObject();
// Dynamically add the fields to the expando
((IDictionary<String, Object>)employee).Add("FirstName", "John");
((IDictionary<String, Object>)employee).Add("Surname", "Smith");
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以将字段动态存储到树结构中,以便我可以拥有名为Name的父字段,然后是名为Firstname和Surname的两个子字段.理想情况下,这可能会扩展到包含更多子级别.我已经在下面做了一些psudo代码来理想地展示我希望它如何工作.(当然这段代码目前会导致错误)
// Create Expando object for testing
dynamic employee = new ExpandoObject();
// Dynamically add the Name
((IDictionary<String, Object>)employee).Add("Name", "");
//Dynamically add the firstname and surname to employee.Name
((IDictionary<String, Object>)employee.Name).Add("FirstName", "John");
((IDictionary<String, Object>)employee.Name).Add("Surname", "Smith");
Run Code Online (Sandbox Code Playgroud) 我在 C# 中有一个ExpandoObject,它已经用大量的字段/属性进行了初始化,我想在 PowerShell 环境中使用这个对象。当我在 PowerShell 中检索这样的对象时,它不会按原样显示所有字段/属性,而是将它们(基于 ExpandoObjects 中的底层字典结构)显示为键/值对。
就我的实现而言,这是非常有问题的,我找不到任何方法将此键/值对转换为字段/属性,就像这样的对象应该表现的那样。将 ExpandoObject 转换为 Object 也不起作用。我错过了什么吗?
我的自定义 DLL (DataCollect.dll) 中的合并函数
public static dynamic merge(dynamic obj)
{
// FIRST : Get the objects out of the table layout.
dynamic Data = retrieveObject(obj);
// SECOND : Check if we're dealing with an array or with a single object.
bool isCollect = isCollection(Data);
// THIRD : Merge objects differently depending on (bool)isCollect.
// The functions below are merge functions that make …Run Code Online (Sandbox Code Playgroud) 我已经按照实施动态的数据网格这个链接.
我正在使用Converter来绑定值ExpandoObject.列显示了学校总单位等值.
Item ItemCount DefaultSchool School1 School2 School3
X-Item 200 100 50 50 0
Run Code Online (Sandbox Code Playgroud)
学校可以随时动态添加.现在,如果我将School4添加到40个单位,我想从默认学校中扣除相同的内容(DefaultSchool = 60,School4 = 40).
我可以在转换器中进行此计算,而ItemsSource也会显示更新的值,但它不会反映在UI上.
我使用TextBox的LostFocus事件MyDataGrid.Items.Refresh,它确实更新了UI,但每次失去焦点时,UI也会闪烁,就像一个刷新的网页一样.
我只需要更新当前行.在我使用时ExpandoObject,我不能使用INotifyPropertyChanged(我相信?),那么在这种情况下最好的方法应该是什么?
那么我该如何更新UI呢?
我正在获取一个JSON对象(可能包含多个级别的JSON数组等),我想将其转换为ExpandoObject。
我想出了如何在实现IDictionary的情况下在运行时向ExpandoObject添加简单属性,但是如何在运行时添加可正确解析的嵌套属性(例如,类似myexpando.somelist.anotherlist.someitem)。
编辑:当前这适用于简单的(第一级)属性:
var exo = new ExpandoObject() as IDictionary<String, Object>;
exo.Add(name, value);
Run Code Online (Sandbox Code Playgroud)
问题是如何获取要嵌套的名称以及如何相应地解析ExpandoObject。
我正在使用Json.Net将json结果反序列化为ExpandoObjects使用如下代码:
var converter = new ExpandoObjectConverter();
dynamic d = JsonConvert.DeserializeObject<ExpandoObject>(json, converter);
Run Code Online (Sandbox Code Playgroud)
除了在json模式的根目录下只有一个列表的响应之外,这对所有事情都很有用,例如:
string json = @"[{""title"": ""the title""}]";
Run Code Online (Sandbox Code Playgroud)
在JsonConvert这个方法的内容:
public static T DeserializeObject<T>(string value, params JsonConverter[] converters)
{
return (T)DeserializeObject(value, typeof(T), converters);
}
Run Code Online (Sandbox Code Playgroud)
返回值DeserializeObject是在其中正确构造的List<object>,ExpandoObject但代码无法尝试将该列表强制转换为ExpandoObject本身(T的值).
我有一个失败的单元测试,可以解决这个问题,但我不确定如何List直接填充ExpandoObject.
这可能吗?DynamicObject有TryGetIndex这样我承担ExpandoObject可以有一个索引.是否有必要通过动态提供索引方法的实现来仔细构建一个类似于列表的expando实例,或者创建一个非expando DynamicObject来保存列表并从动态方法调用中调用正确的方法?
如何使用保留字的键设置 ExpandoObject 的属性?
像这样:
dynamic query = new ExpandoObject();
query.size = 10;
query.date = "2017-04-27";
dynamic match = new {
query = query,
bool = true
}
Run Code Online (Sandbox Code Playgroud) 考虑我有这个简单的c#代码:
dynamic obj = new ExpandoObject();
obj.FirstName = "John";
obj.LastName = "Doe";
Run Code Online (Sandbox Code Playgroud)
John Doe在这种情况下,我想添加将返回全名的方法.我知道以下行会起作用,但不确定它是否是最好的方法
obj.GetFullName = new Func<string>(() => $"{obj.FirstName} {obj.LastName}");
Run Code Online (Sandbox Code Playgroud)
有没有其他方法dynamic object通过该GetFullName方法访问实例?
我可以毫无问题地从 Expandoobject 获取元素内部文本。我不知道如何获取属性的值。
通过这样做Console.WriteLine(obj.Message.Body),我可以在 body 元素中获取预期的字符串。
private void TestXML()
{
string xmlString = @"<?xml version=""1.0"" encoding=""utf-8""?><Message important=""yes"" recevied=""2019-2-12""><Body>Hi there fella!</Body></Message>";
XDocument doc = XDocument.Parse(xmlString);
string json = JsonConvert.SerializeXNode(doc);
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json);
Console.WriteLine(obj.Message);
}
Run Code Online (Sandbox Code Playgroud)
我进行了调试,在下面obj.Message我可以看到 3 个字段:
有没有办法检索带有 @ 前缀的前 2 个字段的值?我不知道如何在动态对象上处理这个@字符。
expandoobject ×10
c# ×9
dynamic ×3
.net ×2
json ×2
json.net ×2
asp.net ×1
c#-4.0 ×1
dictionary ×1
expando ×1
mongodb ×1
powershell ×1
propertygrid ×1
types ×1
wpf ×1
xml ×1