Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JavaScriptConverter、ExpandoObject和动态类型_C#_.net_Json_Javascriptserializer_Expandoobject - Fatal编程技术网

C# JavaScriptConverter、ExpandoObject和动态类型

C# JavaScriptConverter、ExpandoObject和动态类型,c#,.net,json,javascriptserializer,expandoobject,C#,.net,Json,Javascriptserializer,Expandoobject,我有一个这样的小测试班: public class Command { public dynamic MyData { get; set; } } 由于动态MyData我想使用ExpandoObject,所以我可以: Command cmd = new Command(); cmd.MyData = new ExpandoObject(); cmd.MyData.SomeStuff = 4; cmd.MyData.SomeOtherStuff = "hi"; 我正在尝试从json序列

我有一个这样的小测试班:

public class Command
{
    public dynamic MyData { get; set; }
}
由于
动态MyData
我想使用ExpandoObject,所以我可以:

Command cmd = new Command();
cmd.MyData = new ExpandoObject();
cmd.MyData.SomeStuff = 4;
cmd.MyData.SomeOtherStuff = "hi";
我正在尝试从json序列化/反序列化。为此,我使用了
JavaScriptSerializer

我希望上面的示例对象序列化为:

{
    MyData : {
        SomeStuff : 4,
        SomeOtherStuff : "hi"
    }
}
为此,我需要一个
JavaScriptConverter
(取自):

公共类ExpandoJsonConverter:JavaScriptConverter
{
公共重写对象反序列化(IDictionary dictionary、类型、JavaScriptSerializer序列化程序)
{
返回dictionary.ToExpando();
}
公共重写IDictionary序列化(对象obj、JavaScriptSerializer序列化程序)
{
var result=newdictionary();
var dictionary=obj作为IDictionary;
foreach(字典中的变量项)
结果.添加(item.Key,item.Value);
返回结果;
}
公共覆盖IEnumerable SupportedTypes
{
收到
{
返回新的只读集合(新类型[]{typeof(ExpandoObject)});
}
}
}
公共静态类IDictionaryExtensions{
/// 
///将字符串和对象的字典转换为ExpandooObject的扩展方法
///从http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/
/// 
公共静态ExpandoObject to Expando(此IDictionary字典){
var expando=新的ExpandoObject();
var expandoDic=(IDictionary)expando;
//检查字典中的项目并复制键值对)
foreach(字典中的var kvp){
//如果该值也可以转换为ExpandooObject,那么请执行该操作!
if(kvp.Value是IDictionary){
var expandoValue=((IDictionary)kvp.Value).ToExpando();
expandoDic.Add(kvp.Key,expandoValue);
}
否则如果(kvp.Value为ICollection){
//遍历集合并转换任何strin对象字典
//在进入expando对象的过程中
var itemList=新列表();
foreach(在(ICollection)kvp.Value中的变量项){
if(项为IDictionary){
var expandoItem=((IDictionary)项).ToExpando();
itemList.Add(expandoItem);
}
否则{
项目列表。添加(项目);
}
}
expandoDic.Add(kvp.Key,itemList);
}
否则{
expandoDic.Add(kvp);
}
}
返回expando;
}
}
现在,这对于序列化非常有效,但反序列化存在以下问题:

  • 由于
    MyData
    是一个
    dynamic
    对象,并且
    ExpandoJsonConverter
    需要ExpandoObject,因此反序列化到
    MyData
    的数据属于
    IDictionary
    类型
  • 如果我将
    dynamic MyData
    更改为
    ExpandoObject MyData
    ,我将不能说
    cmd.MyData.SomeStuff=4,编译器会告诉我“ExpandooObject没有名为SomeStuff的属性”
  • 最后,我可以将
    dynamic
    添加到支持的
    ExpandoJsonConverter
    类型列表中,通过等待,您不能执行
    typeof(dynamic)

有人知道一个整洁的解决方法吗?我真的很喜欢这个功能,但是我不能使用第三方序列化库,比如Newtonsoft。谢谢。

反序列化到
ExpandoObject
,但声明变量
dynamic
,即您需要的是
dynamic d=js。反序列化(json)


能满足您的要求吗?谢谢您的回复。同样,整个主题都是关于序列化为JSON的,我已经实现了这一点。我的问题是相反的(反序列化JSON),它返回字典而不是ExpandoObject。
public class ExpandoJsonConverter : JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        return dictionary.ToExpando();
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var result = new Dictionary<string, object>();
        var dictionary = obj as IDictionary<string, object>;
        foreach (var item in dictionary)
            result.Add(item.Key, item.Value);
        return result;
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get
        {
            return new ReadOnlyCollection<Type>(new Type[] { typeof(ExpandoObject) });
        }
    }
}

public static class IDictionaryExtensions {
    /// <summary>
    /// Extension method that turns a dictionary of string and object to an ExpandoObject
    /// Snagged from http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/
    /// </summary>
    public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary) {
        var expando = new ExpandoObject();
        var expandoDic = (IDictionary<string, object>)expando;

        // go through the items in the dictionary and copy over the key value pairs)
        foreach (var kvp in dictionary) {
            // if the value can also be turned into an ExpandoObject, then do it!
            if (kvp.Value is IDictionary<string, object>) {
                var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
                expandoDic.Add(kvp.Key, expandoValue);
            }
            else if (kvp.Value is ICollection) {
                // iterate through the collection and convert any strin-object dictionaries
                // along the way into expando objects
                var itemList = new List<object>();
                foreach (var item in (ICollection)kvp.Value) {
                    if (item is IDictionary<string, object>) {
                        var expandoItem = ((IDictionary<string, object>)item).ToExpando();
                        itemList.Add(expandoItem);
                    }
                    else {
                        itemList.Add(item);
                    }
                }

                expandoDic.Add(kvp.Key, itemList);
            }
            else {
                expandoDic.Add(kvp);
            }
        }

        return expando;
    }
}
string json = @"{
    MyData : {
        SomeStuff : 4,
        SomeOtherStuff : ""hi""
    }
}";

var js = new JavaScriptSerializer();
js.RegisterConverters(new[] { new ExpandoJsonConverter() });    
dynamic d = js.Deserialize<ExpandoObject>(json);    
Console.WriteLine(d.MyData.SomeOtherStuff);
var cmd = new Command { MyData = d };
Console.WriteLine(cmd.MyData.SomeStuff);