如何在 javascript 扩展样式中扩展动态 C# 对象?

How to extend dynamic c# object in javascript extend style?

** 这是一个自我回答的问题,因为我找到了解决方案,但我没有在这里找到它 **

用例

来自 应用程序 A(C# 后端)的非明确定义的结构化数据必须传递给 应用程序 B(ASP.Net C# 应用程序,其中 SignalR 前端)使用 HTTP,它将使用 SignalR 简单地将消息传递给 javascript 客户端。

数据用于实时登录。

为什么不创建 classes? 因为传入的数据是可以变化的,还没有被Application B解析,所以两端的代码不能共享class(C#/JavaScript).

另外,我希望能够做这样的事情:

var foo = DynamicExtend(
    new { propExtendedFromDynamic1 = true }, 
    new { propExtendedFromDynamic2 = true }
);
string jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
dynamic unserializedFoo = JObject.Parse(jsonText);

使用 expando 对象

由于动态对象不易修改,所以需要使用ExpandoObject。

唯一的缺点是它无法完成具有其他动态属性的原始动态对象,并且仍然使用与 $.extend(true, {p1:1},{p2:2}) 相同的引用(如果你知道 jQuery 你就会明白) .

public static dynamic DynamicExtend(params dynamic[] extendedItems)
{
        if (extendedItems == null || extendedItems.Length == 0 || extendedItems[0] == null)
            throw new Exception("Missing initial dynamic property");

        if (extendedItems.Length == 1)
            return extendedItems.First();

        dynamic r = new ExpandoObject();
        // We will need that casted value or the r[propertyName]="someValue" will fail
        var dynamicReturnedEditable = (IDictionary<string, object>)r;

        // For each dynamic object passed in
        foreach (dynamic extensionHolder in extendedItems)
        {
            var expandoCase = extensionHolder as IDictionary<string, object>;
            if (expandoCase == null)
            {
                // Pour chaque propriété
                foreach (var property in ((object)extensionHolder).GetType().GetProperties())
                {
                    // Faire la copie sur l'ExpandoObject (qui gère nativement le rajout de propriété) en utilisant les données extraites de l'objet dynamique
                    dynamicReturnedEditable[property.Name] = property.GetValue(extensionHolder, null);
                }
            }
            else
            {
                foreach (var propertyName in expandoCase.Keys)
                {
                    // Faire la copie sur l'ExpandoObject (qui gère nativement le rajout de propriété) en utilisant les données extraites de l'objet dynamique
                    dynamicReturnedEditable[propertyName] = expandoCase[propertyName];
                }
            }
        }

        return r;
}

注意:例如,它不支持由 JObject.Parse(jsonText); 产生的参数,因为它必须从中读取属性。