我想在运行时动态地向ExpandoObject添加属性.所以例如添加一个字符串属性调用NewProp我想写类似的东西
var x = new ExpandoObject();
x.AddProperty("NewProp", System.String);
Run Code Online (Sandbox Code Playgroud)
这很容易吗?
在javascript中,您可以使用undefined关键字检测属性是否已定义:
if( typeof data.myProperty == "undefined" ) ...
Run Code Online (Sandbox Code Playgroud)
你如何在C#中使用带有ExpandoObject
和不带异常的动态关键字来做到这一点?
之间有什么区别System.Dynamic.ExpandoObject
,System.Dynamic.DynamicObject
和dynamic
?
在哪些情况下你使用这些类型?
我非常喜欢在运行ExpandoObject
时编译服务器端动态对象,但是在JSON序列化期间我遇到了麻烦.首先,我实例化对象:
dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.在我的MVC控制器中,我想将其作为JsonResult发送,所以我这样做:
return new JsonResult(expando);
Run Code Online (Sandbox Code Playgroud)
这将JSON序列化到下面,由浏览器使用:
[{"Key":"SomeProp", "Value": SomeValueOrClass}]
Run Code Online (Sandbox Code Playgroud)
但是,我真正喜欢的是看到这个:
{SomeProp: SomeValueOrClass}
Run Code Online (Sandbox Code Playgroud)
我知道我可以实现这个,如果我使用dynamic
而不是ExpandoObject
- JsonResult
能够将dynamic
属性和值序列化为单个对象(没有Key或Value业务),但我需要使用的原因ExpandoObject
是因为我不知道所有的直到运行时我想要的对象属性,据我所知,我不能动态地添加属性dynamic
而不使用ExpandoObject
.
我可能不得不在我的javascript中筛选"关键","价值"业务,但我希望在将其发送给客户之前解决这个问题.谢谢你的帮助!
我做错了什么,或者以下代码真的不可能?
dynamic x = new ExpandoObject { Foo = 12, Bar = "twelve" };
Run Code Online (Sandbox Code Playgroud)
如果这确实不可能,是否有另一种单行方式来实例化具有两个属性的ExpandoObject?
为什么C#团队会选择禁止使用与常规对象,匿名对象和枚举/列表相同的初始化语法?
更新
我问过这个问题是因为我试图向珍珠爱好者展示C#的酷炫新动态特性,但后来由于无法做到我认为是一个逻辑实例化的东西而陷入困境ExpandoObject
.感谢Hans Passant的回答,我意识到这ExpandoObject
是错误的工具.我的真正目标是使用C#的动态功能从方法返回两个命名值.汉斯指出,dynamic
关键字对此非常完美.我没有需要一个ExpandoObject
完成它的所有开销.
因此,如果您想从方法中返回一对命名值,并且您不关心类型安全性,智能感知,重构或性能,这可以很好地工作:
public dynamic CreateFooBar()
{
return new { Foo = 42, Bar = "Hello" };
}
Run Code Online (Sandbox Code Playgroud)
用法:
dynamic fooBar = CreateFooBar();
var foo = fooBar.Foo;
var bar = fooBar.Bar;
Run Code Online (Sandbox Code Playgroud) 我正在尝试学习C#4.0附带的所有新东西.我无法理解DynamicObject
和ExpandoObject
类型之间的差异.它似乎DynamicObject
用于例如当您想要从Python脚本访问变量以及ExpandoObject
与COM/Office对象交谈时.我对吗?它们的用途有何不同?
今天在研究C#动态时,有些东西让我感到惊讶(我从未使用过它们,但最近我一直在试验Nancy web框架).我发现我不能这样做:
dynamic expando = new ExpandoObject();
expando.name = "John";
Console.WriteLine(expando["name"]);
Run Code Online (Sandbox Code Playgroud)
最后一行抛出异常:
无法将[]索引应用于"System.Dynamic.ExpandoObject"类型的表达式
我理解错误信息,但我不明白为什么会这样.我查看了ExpandoObject的文档,它显式实现IDictionary<,>
,因此有一个this.[index]
方法(MSDN).为什么我不能打电话给它?
当然,没有什么可以阻止我ExpandoObject
手动向下翻译到字典然后索引到它,但这种方式无视这一点; 它也没有解释Expando如何能够隐藏其中一个接口的方法.
这里发生了什么?
我试图在WPF数据网格中显示查询的结果.我绑定的ItemsSource类型是IEnumerable<dynamic>
.由于返回的字段直到运行时才确定,因此在评估查询之前我不知道数据的类型.每个"行"都返回为ExpandoObject
具有表示字段的动态属性.
我希望AutoGenerateColumns
(如下所示)能够从ExpandoObject
静态类型生成列,但它似乎不会.
<DataGrid AutoGenerateColumns="True" ItemsSource="{Binding Results}"/>
Run Code Online (Sandbox Code Playgroud)
无论如何要以声明方式执行此操作,还是必须使用某些C#进行必要的操作?
编辑
好的,这会给我正确的列:
// ExpandoObject implements IDictionary<string,object>
IEnumerable<IDictionary<string, object>> rows = dataGrid1.ItemsSource.OfType<IDictionary<string, object>>();
IEnumerable<string> columns = rows.SelectMany(d => d.Keys).Distinct(StringComparer.OrdinalIgnoreCase);
foreach (string s in columns)
dataGrid1.Columns.Add(new DataGridTextColumn { Header = s });
Run Code Online (Sandbox Code Playgroud)
所以现在只需要弄清楚如何将列绑定到IDictionary值.
在我的Windows应用商店应用中,我有一个填充了ExpandoObjects的列表.数据绑定适用于初始值,但不适用于我在下载文件后异步设置的图像属性:
public static async void Set<T>(this ExpandoObject thisObject, string property, Func<Task<T>> setter) {
var expando = thisObject as IDictionary<string, Object>;
if (!expando.ContainsKey(property)) {
expando.Add(property, null);
}
expando[property] = await setter.Invoke();
}
Run Code Online (Sandbox Code Playgroud)
在ExpandoObject上连接到PropertyChanged事件确认它是针对所有对象触发的.新属性附加到对象,值正确,但ListView中的项目未完全更新.
该列表包含14个对象.如果我使用常规类型对象而不是ExpandoObjects并使用相同的图像属性异步设置,则14个对象中的一些将在视图中更新(当前不可见的对象).如果我在类中实现了INotifyPropertyChanged,那么所有14个都会更新.使用ExpandoObjects我得到的确切行为与没有INPC的类型对象一样:更新当前不可见的项目.
所以似乎PropertyChanged不使用ExpandoObject和数据绑定.
它在WPF中按预期工作,但不在Store App中工作.查看比较:https: //sites.google.com/site/moramatte/ExpandoComparison.zip ?attredirects = 0&d = 1
在python中,如何在没有预定义类的情况下创建新对象,然后动态添加属性?
例:
dynamic_object = Dynamic()
dynamic_object.dynamic_property_a = "abc"
dynamic_object.dynamic_property_b = "abcdefg"
Run Code Online (Sandbox Code Playgroud)
最好的方法是什么?
编辑因为许多人在评论中建议我可能不需要这个.
问题是我有一个序列化对象属性的函数.出于这个原因,我不想因为一些构造函数的限制而创建一个期望类的对象,而是创建一个类似的对象,让我们说像模拟,添加我需要的任何"自定义"属性,然后将其反馈给功能.
expandoobject ×10
dynamic ×7
c# ×6
.net ×2
c#-4.0 ×2
asp.net-mvc ×1
binding ×1
class ×1
datagrid ×1
javascript ×1
json ×1
object ×1
oop ×1
python ×1
wpf ×1