C# - 在 .Net Core 中重新应用 JS 对象的操作
C# - Reapply the manipulation of JS Object in .Net Core
我在这里搜索,看到了几个类似的问题,但大多数是几年前创建的。
所以,我将用一个简单的 JS 示例打开question/discussion,介绍这种语言如何简化他的对象中的修改、读取、写入道具。
在JS上检查以下代码:
const dynamicObject = {
a: [1, 2],
b: "String val",
c: 10,
d: { sa: 1, sb: null, sc: [1, 2, 3] }
};
// Add new props
const newProp = "e";
dynamicObject[newProp] = "New val";
dynamicObject.f = false;
dynamicObject["d"]["sd"] = null
dynamicObject["d"].se = null
// Modify props
const prop = 'a'
dynamicObject[prop].push(3)
dynamicObject.b += " ABCD"
// Modify children props of another prop
dynamicObject.d.sb = ["New", "Array"]
dynamicObject.d["sa"] += 5
dynamicObject["d"]["sa"] += 5
// Read props
const propValue = dynamicObject[prop]
console.log(propValue)
const propValueString = dynamicObject.b
console.log(propValueString)
查看在线结果here
我尝试使用 C# 重新应用此方法:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
dynamic dynamicObject = new {
a = new int[] {1, 2},
b = "String val",
c = 10,
d = new { sa = 1, sb = "abv", sc = new int[] { 1, 2, 3 } }
};
var DO = (IDictionary<string, object>)dynamicObject;
// Add new props
const string newProp = "e";
dynamicObject[newProp] = "New val";
dynamicObject.f = false;
dynamicObject["d"]["sd"] = null;
dynamicObject["d"].se = null;
// Modify props
const string prop = "a";
dynamicObject[prop].push(3);
dynamicObject.b += " ABCD";
// Modify children props of another prop
dynamicObject.d.sb = new string[] { "New", "Array" };
dynamicObject.d["sa"] += 5;
dynamicObject["d"]["sa"] += 5;
// Read props
object propValue = dynamicObject[prop];
object propValueString = dynamicObject.b;
string result = JsonConvert.SerializeObject(dynamicObject);
Console.WriteLine(result);
}
}
.Net Fiddle 示例 here
但显然没有达到预期效果
我知道我们可以使用 ExpandoObject
或 dynamic
或通过将对象转换为 IDictionary<string, object>
的字符串参数访问道具。
我不想将讨论重点放在 C# 是一种强类型语言的区别上。
但是,C# 仍然没有实现任何 structure/object/library 来轻松管理像 JS 这样的对象操作?
重要提示:
我做了另一个版本,做了一些改进:
Version 2
我自己制作了 Class 以使用 C# Net Core
与 Object/Dynamic/ExpandoObjects 进行更动态的交互
完整代码如下:
namespace FW {
public class Expando
{
public Expando(dynamic value)
{
expando = ToExpando(value);
}
public ExpandoObject root { get => expando; }
private ExpandoObject expando { get; set; }
private ExpandoObject ToExpando(dynamic dynamicObject)
{
if ((dynamicObject as object).GetType().Name == "ExpandoObject") return dynamicObject;
if (!(dynamicObject as object).GetType().IsGenericType) throw new Exception("No generic type");
ExpandoObject expando = new ExpandoObject();
((object)dynamicObject)
.GetType()
.GetProperties()
.ToList()
.ForEach(p => expando.fwAddProperty(p.Name, p.GetValue(dynamicObject) as object));
return expando;
}
public dynamic this[string prop]
{
get => expando.fwReadProperty(prop);
set => expando.fwAddProperty(prop, value as object);
}
public dynamic this[params string[] props]
{
get
{
ExpandoObject returnValue = expando;
foreach (string prop in props)
{
var temp = returnValue.fwReadProperty(prop);
try { returnValue = ToExpando(temp); }
catch { return temp as object; }
}
return returnValue;
}
set
{
List<ExpandoObject> list = new List<ExpandoObject>();
list.Add(expando);
foreach (var prop in props)
{
var newProp = list.Last().fwReadProperty(prop);
if (newProp != null)
{
try { list.Add(ToExpando(newProp)); }
catch { }
}
else if (prop != props.Last())
{
ExpandoObject expandoTemp = new ExpandoObject();
list.Add(expandoTemp);
}
}
List<string> nodeProps = props.ToList();
list.Last().fwAddProperty(nodeProps.Last(), value as object);
nodeProps.RemoveAt(nodeProps.Count - 1);
ExpandoObject ExpandoTemp = list.Last();
list.RemoveAt(list.Count - 1);
while (list.Count != 0)
{
var node = list.Last();
list.RemoveAt(list.Count - 1);
node.fwAddProperty(nodeProps.Last(), ExpandoTemp as object);
nodeProps.RemoveAt(nodeProps.Count - 1);
ExpandoTemp = node;
}
expando = ExpandoTemp;
}
}
}
public static class extExpandoObject
{
public static void fwAddProperty(this ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
public static object fwReadProperty(this ExpandoObject expando, string propertyName)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
return expandoDict[propertyName];
else
return null;
}
}
}
下面是实现的例子:
public class Program
{
public static void Main()
{
FW.Expando dynamicObject =
new FW.Expando(new
{
a = new int[] { 1, 2 },
b = "String val",
c = 10,
d = new { sa = 1, sb = "abv", sc = new int[] { 1, 2, 3 } }
});
// Add new props
const string newProp = "e";
dynamicObject[newProp] = "New val";
dynamicObject["f"] = false;
dynamicObject["d", "sd"] = "SDSDSD";
var a = dynamicObject["d", "sd"];
dynamicObject["d", "se"] = null;
// Modify props
const string prop = "a";
dynamicObject[prop] = (dynamicObject[prop] as int[]).Append(3).ToArray();
dynamicObject["b"] += " ABCD";
// Modify children props of another prop
dynamicObject["d", "sb"] = new string[] { "New", "Array" };
dynamicObject["d", "sa"] += 5;
dynamicObject["d", "sa"] = new { dz = "ABA", zz = "WCC", ZXXX = new { Y1 = "1", Y2 = "2" } };
dynamicObject["parent", "node"] = "New field";
dynamicObject["parent-node", "node-lvl1", "node-lvl1.1"] = "P > 1 > 1.1";
dynamicObject["parent-node", "node-lvl1", "node-lvl1.2"] = "P > 1 > 1.2";
dynamicObject["parent-node", "node-lvl2", "node-lvl2.1"] = "P > 2 > 2.1";
dynamicObject["parent-node", "m-node", "sub1", "sub2", "sub3"] = "3 Sublevels";
// Read props
object propValue = dynamicObject[prop];
object propValueString = dynamicObject["b"];
string result = Newtonsoft.Json.JsonConvert.SerializeObject(dynamicObject.root);
// CHECK MORE EASILY THE RESULT: https://jsonformatter.curiousconcept.com/
Console.WriteLine("\r\n" + result + "\r\n");
}
}
这是 JSON 中的结果:
{
"a":[
1,
2,
3
],
"b":"String val ABCD",
"c":10,
"d":{
"sa":{
"dz":"ABA",
"zz":"WCC",
"ZXXX":{
"Y1":"1",
"Y2":"2"
}
},
"sb":[
"New",
"Array"
],
"sc":[
1,
2,
3
],
"sd":"SDSDSD",
"se":null
},
"e":"New val",
"f":false,
"parent":{
"node":"New field"
},
"parent-node":{
"node-lvl1":{
"node-lvl1.1":"P > 1 > 1.1",
"node-lvl1.2":"P > 1 > 1.2"
},
"node-lvl2":{
"node-lvl2.1":"P > 2 > 2.1"
},
"m-node":{
"sub1":{
"sub2":{
"sub3":"3 Sublevels"
}
}
}
}
}
你怎么看?还有其他反馈或意见吗?
只是免责声明,JSON 中的子级别在单个数组中使用。
- 写入:
dynamicObject["parent", "node"] = "New field";
- 阅读:
dynamicObject["parent", "node"];
而且我无法在不使用字符串的情况下进行实现。
例如:dynamicObject["myProp"] = "propValue"
,而不是 dynamicObject.myProp = "propValue"
我在这里搜索,看到了几个类似的问题,但大多数是几年前创建的。
所以,我将用一个简单的 JS 示例打开question/discussion,介绍这种语言如何简化他的对象中的修改、读取、写入道具。
在JS上检查以下代码:
const dynamicObject = {
a: [1, 2],
b: "String val",
c: 10,
d: { sa: 1, sb: null, sc: [1, 2, 3] }
};
// Add new props
const newProp = "e";
dynamicObject[newProp] = "New val";
dynamicObject.f = false;
dynamicObject["d"]["sd"] = null
dynamicObject["d"].se = null
// Modify props
const prop = 'a'
dynamicObject[prop].push(3)
dynamicObject.b += " ABCD"
// Modify children props of another prop
dynamicObject.d.sb = ["New", "Array"]
dynamicObject.d["sa"] += 5
dynamicObject["d"]["sa"] += 5
// Read props
const propValue = dynamicObject[prop]
console.log(propValue)
const propValueString = dynamicObject.b
console.log(propValueString)
查看在线结果here
我尝试使用 C# 重新应用此方法:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
dynamic dynamicObject = new {
a = new int[] {1, 2},
b = "String val",
c = 10,
d = new { sa = 1, sb = "abv", sc = new int[] { 1, 2, 3 } }
};
var DO = (IDictionary<string, object>)dynamicObject;
// Add new props
const string newProp = "e";
dynamicObject[newProp] = "New val";
dynamicObject.f = false;
dynamicObject["d"]["sd"] = null;
dynamicObject["d"].se = null;
// Modify props
const string prop = "a";
dynamicObject[prop].push(3);
dynamicObject.b += " ABCD";
// Modify children props of another prop
dynamicObject.d.sb = new string[] { "New", "Array" };
dynamicObject.d["sa"] += 5;
dynamicObject["d"]["sa"] += 5;
// Read props
object propValue = dynamicObject[prop];
object propValueString = dynamicObject.b;
string result = JsonConvert.SerializeObject(dynamicObject);
Console.WriteLine(result);
}
}
.Net Fiddle 示例 here
但显然没有达到预期效果
我知道我们可以使用 ExpandoObject
或 dynamic
或通过将对象转换为 IDictionary<string, object>
的字符串参数访问道具。
我不想将讨论重点放在 C# 是一种强类型语言的区别上。
但是,C# 仍然没有实现任何 structure/object/library 来轻松管理像 JS 这样的对象操作?
重要提示:
我做了另一个版本,做了一些改进: Version 2
我自己制作了 Class 以使用 C# Net Core
与 Object/Dynamic/ExpandoObjects 进行更动态的交互完整代码如下:
namespace FW {
public class Expando
{
public Expando(dynamic value)
{
expando = ToExpando(value);
}
public ExpandoObject root { get => expando; }
private ExpandoObject expando { get; set; }
private ExpandoObject ToExpando(dynamic dynamicObject)
{
if ((dynamicObject as object).GetType().Name == "ExpandoObject") return dynamicObject;
if (!(dynamicObject as object).GetType().IsGenericType) throw new Exception("No generic type");
ExpandoObject expando = new ExpandoObject();
((object)dynamicObject)
.GetType()
.GetProperties()
.ToList()
.ForEach(p => expando.fwAddProperty(p.Name, p.GetValue(dynamicObject) as object));
return expando;
}
public dynamic this[string prop]
{
get => expando.fwReadProperty(prop);
set => expando.fwAddProperty(prop, value as object);
}
public dynamic this[params string[] props]
{
get
{
ExpandoObject returnValue = expando;
foreach (string prop in props)
{
var temp = returnValue.fwReadProperty(prop);
try { returnValue = ToExpando(temp); }
catch { return temp as object; }
}
return returnValue;
}
set
{
List<ExpandoObject> list = new List<ExpandoObject>();
list.Add(expando);
foreach (var prop in props)
{
var newProp = list.Last().fwReadProperty(prop);
if (newProp != null)
{
try { list.Add(ToExpando(newProp)); }
catch { }
}
else if (prop != props.Last())
{
ExpandoObject expandoTemp = new ExpandoObject();
list.Add(expandoTemp);
}
}
List<string> nodeProps = props.ToList();
list.Last().fwAddProperty(nodeProps.Last(), value as object);
nodeProps.RemoveAt(nodeProps.Count - 1);
ExpandoObject ExpandoTemp = list.Last();
list.RemoveAt(list.Count - 1);
while (list.Count != 0)
{
var node = list.Last();
list.RemoveAt(list.Count - 1);
node.fwAddProperty(nodeProps.Last(), ExpandoTemp as object);
nodeProps.RemoveAt(nodeProps.Count - 1);
ExpandoTemp = node;
}
expando = ExpandoTemp;
}
}
}
public static class extExpandoObject
{
public static void fwAddProperty(this ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
public static object fwReadProperty(this ExpandoObject expando, string propertyName)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
return expandoDict[propertyName];
else
return null;
}
}
}
下面是实现的例子:
public class Program
{
public static void Main()
{
FW.Expando dynamicObject =
new FW.Expando(new
{
a = new int[] { 1, 2 },
b = "String val",
c = 10,
d = new { sa = 1, sb = "abv", sc = new int[] { 1, 2, 3 } }
});
// Add new props
const string newProp = "e";
dynamicObject[newProp] = "New val";
dynamicObject["f"] = false;
dynamicObject["d", "sd"] = "SDSDSD";
var a = dynamicObject["d", "sd"];
dynamicObject["d", "se"] = null;
// Modify props
const string prop = "a";
dynamicObject[prop] = (dynamicObject[prop] as int[]).Append(3).ToArray();
dynamicObject["b"] += " ABCD";
// Modify children props of another prop
dynamicObject["d", "sb"] = new string[] { "New", "Array" };
dynamicObject["d", "sa"] += 5;
dynamicObject["d", "sa"] = new { dz = "ABA", zz = "WCC", ZXXX = new { Y1 = "1", Y2 = "2" } };
dynamicObject["parent", "node"] = "New field";
dynamicObject["parent-node", "node-lvl1", "node-lvl1.1"] = "P > 1 > 1.1";
dynamicObject["parent-node", "node-lvl1", "node-lvl1.2"] = "P > 1 > 1.2";
dynamicObject["parent-node", "node-lvl2", "node-lvl2.1"] = "P > 2 > 2.1";
dynamicObject["parent-node", "m-node", "sub1", "sub2", "sub3"] = "3 Sublevels";
// Read props
object propValue = dynamicObject[prop];
object propValueString = dynamicObject["b"];
string result = Newtonsoft.Json.JsonConvert.SerializeObject(dynamicObject.root);
// CHECK MORE EASILY THE RESULT: https://jsonformatter.curiousconcept.com/
Console.WriteLine("\r\n" + result + "\r\n");
}
}
这是 JSON 中的结果:
{
"a":[
1,
2,
3
],
"b":"String val ABCD",
"c":10,
"d":{
"sa":{
"dz":"ABA",
"zz":"WCC",
"ZXXX":{
"Y1":"1",
"Y2":"2"
}
},
"sb":[
"New",
"Array"
],
"sc":[
1,
2,
3
],
"sd":"SDSDSD",
"se":null
},
"e":"New val",
"f":false,
"parent":{
"node":"New field"
},
"parent-node":{
"node-lvl1":{
"node-lvl1.1":"P > 1 > 1.1",
"node-lvl1.2":"P > 1 > 1.2"
},
"node-lvl2":{
"node-lvl2.1":"P > 2 > 2.1"
},
"m-node":{
"sub1":{
"sub2":{
"sub3":"3 Sublevels"
}
}
}
}
}
你怎么看?还有其他反馈或意见吗?
只是免责声明,JSON 中的子级别在单个数组中使用。
- 写入:
dynamicObject["parent", "node"] = "New field";
- 阅读:
dynamicObject["parent", "node"];
而且我无法在不使用字符串的情况下进行实现。
例如:dynamicObject["myProp"] = "propValue"
,而不是 dynamicObject.myProp = "propValue"