C#深度/嵌套/递归合并动态/expando对象我需要在C#中“合并”2个动态对象。我在stackexchange上找到的所有内容都只涵盖非递归合并。但我正在寻找递归或深度合并的东西,比如jQuery的$.extend(obj1,obj2)函数。两个成员发生冲突后,应遵守以下规则:所有其他类型都可能被丢弃,并且不需要出现在生成的动态对象中这是一个可能的合并示例:dynamicDefaultConfig=new{BlacklistedDomains=newstring[]{"domain1.com"},ExternalConfigFile="blacklist.txt",UseSockets=new[]{new{IP="127.0.0.1",Port="80"},new{IP="127.0.0.2",Port=“8080”}}};dynamicUserSpecifiedConfig=new{BlacklistedDomain=newstring[]{"example1.com"},ExternalConfigFile="C:\my_blacklist.txt"};varresult=Merge(UserSpecifiedConfig,DefaultConfig);//结果现在应该等于:varresult_equal=new{BlacklistedDomains=newstring[]{"domain1.com","example1.com"},ExternalConfigFile="C:\my_blacklist.txt",UseSockets=new[]{new{IP="127.0.0.1",Port="80"},new{IP="127.0.0.2",Port="8080"}}};任何想法如何做到这一点?是的,这有点长,但请检查一下。它是使用Reflection.Emit实现的。我的未决问题是如何实现ToString()覆盖,以便您可以进行字符串比较。这些值是来自配置文件还是其他?如果它们是JSON格式,我认为你可能比使用JsonSerializer做得更糟。取决于你想要什么。您可以使用Expando对象摆脱循环底部的Reflection.Emit废话:varresult=newExpandoObject();varresultDict=结果作为IDictionary;foreach(resVals.Keys中的字符串键){resultDict.Add(key,resVals[key]);}返回结果;我看不到解析原始对象树的混乱代码,但不是立即。我想听听一些其他的意见。DLR对我来说是一个相对较新的基地。使用系统;使用System.Collections.Generic;使用系统诊断;使用System.Linq;使用System.Reflection;使用System.Reflection.Emit;使用System.Runtime.CompilerServices;使用系统线程;namespaceConsoleApplication1{classProgram{staticvoidMain(string[]args){dynamicDefaultConfig=new{BlacklistedDomains=newstring[]{“domain1.com”},ExternalConfigFile=“blacklist.txt”,UseSockets=new[]{new{IP="127.0.0.1",端口="80"},新{IP="127.0.0.2",端口="8080"}}};dynamicUserSpecifiedConfig=new{BlacklistedDomains=newstring[]{"example1.com"},ExternalConfigFile="C:\my_blacklist.txt"};varresult=Merge(UserSpecifiedConfig,DefaultConfig);//结果现在应该等于:varresult_equal=new{BlacklistedDomains=newstring[]{"domain1.com","example1.com"},ExternalConfigFile="C:\my_blacklist.txt",UseSockets=new[]{new{IP="127.0.0.1",Port="80"},new{IP="127.0.0.2",Port="8080"}}};Debug.Assert(result.Equals(result_equal));}//////合并两个动态对象的属性,以LHS为主////////////staticdynamicMerge(dynamiclhs,dynamicrhs){//获取匿名类型定义TypelhsType=((Type)((dynamic)lhs).GetType());TyperhsType=((Type)((dynamic)rhs).GetType());objectresult=new{};varresProps=newDictionary();varresVals=newDictionary();varlProps=lhsType.GetProperties().ToDictionary(prop=>prop.Name);varrProps=rhsType.GetProperties().ToDictionary(prop=>prop.Name);foreach(lProps.Keys中的字符串leftPropKey){varlPropInfo=lProps[leftPropKey];resProps.Add(leftPropKey,lPropInfo);varlhsVal=Convert.ChangeType(lPropInfo.GetValue(lhs,null),lPropInfo.PropertyType);if(rProps.ContainsKey(leftPropKey)){PropertyInforPropInfo;rPropInfo=rProps[leftPropKey];varrhsVal=Convert.ChangeType(rPropInfo.GetValue(rhs,null),rPropInfo.PropertyType);对象setVal=null;如果(lPropInfo.PropertyType.IsAnonymousType()){setVal=Merge(lhsVal,rhsVal);}elseif(lPropInfo.PropertyType.IsArray){varbound=((Array)lhsVal).Length+((Array)rhsVal).Length;varcons=lPropInfo.PropertyType.GetConstructor(newType[]{typeof(int)});动态newArray=cons.Invoke(newobject[]{bound});//newArray=((Array)lhsVal).Clone();诠释我=0;while(iproperties){AppDomainmyDomain=Thread.GetDomain();组装asm=type.Assembly;AssemblyBuilderassemblyBuilder=myDomain.DefineDynamicAssembly(asm.GetName(),AssemblyBuilderAccess.Run);ModuleBuildermoduleBuilder=assemblyBuilder.DefineDynamicModule(type.Module.Name);TypeBuildertypeBuilder=moduleBuilder.DefineType(type.Name,TypeAttributes.Public);foreach(properties.Keys中的字符串键){stringpropertyName=key;类型propertyType=properties[key].PropertyType;FieldBuilderfieldBuilder=typeBuilder.DefineField("_"+propertyName,propertyType,FieldAttributes.Private);PropertyBuilderpropertyBuilder=typeBuilder.DefineProperty(propertyName,PropertyAttributes.HasDefault,propertyType,newType[]{});//首先,我们将属性的“get”访问器的行为定义为一个方法。MethodBuildergetMethodBuilder=typeBuilder.DefineMethod("Get"+propertyName,MethodAttributes.Public,propertyType,newType[]{});ILGeneratorgetMethodIL=getMethodBuilder.GetILGenerator();getMethodIL.Emit(OpCodes.Ldarg_0);getMethodIL.Emit(OpCodes.Ldfld,fieldBuilder);getMethodIL.Emit(OpCodes.Ret);//现在,我们将为属性定义“set”访问器的行为。MethodBuildersetMethodBuilder=typeBuilder.DefineMethod("Set"+propertyName,MethodAttributes.Public,null,newType[]{propertyType});ILGeneratorcustNameSetIL=setMethodBuilder.GetILGenerator();custNameSetIL.Emit(OpCodes.Ldarg_0);custNameSetIL.Emit(OpCodes.Ldarg_1);客户名称eSetIL.Emit(OpCodes.Stfld,fieldBuilder);custNameSetIL.Emit(OpCodes.Ret);//最后,我们必须将上面创建的两个方法映射到我们的PropertyBuilder//它们对应的行为,分别为“get”和“set”.propertyBuilder.SetGetMethod(getMethodBuilder);propertyBuilder.SetSetMethod(setMethodBuilder);}//MethodBuildertoStringMethodBuilder=typeBuilder.DefineMethod(//"ToString",//MethodAttributes.Public,//typeof(string),//newType[]{}//);返回typeBuilder.CreateType();}publicstaticBooleanIsAnonymousType(thisTypetype){BooleanhasCompilerGeneratedAttribute=type.GetCustomAttributes(typeof(CompilerGeneratedAttribute),false).Count()>0;布尔nameContainsAnonymousType=类型。FullName.Contains("AnonymousType");BooleanisAnonymousType=hasCompilerGeneratedAttribute&&nameContainsAnonymousType;返回是匿名类型;这对我有用,但我相信如果有一些爱和关注它会看起来更好它不包括你的类型检查,但添加它听起来很简单。虽然这不是一个完美的答案,但我希望它能让您更接近解决方案。对DynamicIntoExpando(…)的后续调用将继续追加并覆盖现有Source结构的新值和现有值。您可以根据需要多次调用它。MergeDynamic()函数说明了如何动态地将两个ExpandoObject合并为一个。代码基本上遍历动态值,检查类型,并适当地递归合并到任何深度。出于我自己的目的,我将其包装在一个辅助类中。以上就是C#学习教程的全部内容:C#深度/嵌套/递归合并动态/扩展对象。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注——usingSystem.Dynamic;//对于ExpandoObject...publicstaticclassDynamicHelper{//我们期望输入是IDictionary类型publicstaticExpandoObjectMergeDynamic(dynamicSource,dynamicAdditional){ExpandoObjectResult=newExpandoObject();//首先将'source'复制到ResultDynamicIntoExpando(Result,Source);//然后复制其他字段,根据需要大胆覆盖源DynamicIntoExpando(Result,Additional);//完成返回结果;}publicstaticvoidDynamicIntoExpando(ExpandoObjectResult,dynamicSource,stringKey=null){//转换它以便于使用。varR=结果作为IDictionary;if(SourceisIDictionary){varS=SourceasIDictionary;ExpandoObjectNewDict=newExpandoObject();if(Key==null){NewDict=Result;}elseif(R.ContainsKey(Key)){//已经存在,覆盖NewDict=R[Key];}varND=NewDict作为IDictionar是;foreach(S.Keys中的字符串键){ExpandoObjectNewDictEntry=newExpandoObject();varNDE=NewDictEntryasIDictionary;if(ND.ContainsKey(key)){NDE[key]=ND[key];}elseif(R.ContainsKey(key)){NDE[key]=R[key];}DynamicIntoExpando(NewDictEntry,S[key],key);if(!R.ContainsKey(key)){ND[key]=((IDictionary)NewDictEntry)[key];}}if(Key==null){R=NewDict;}elseif(!R.ContainsKey(Key)){R.Add(Key,NewDict);}}elseif(SourceisIList){varS=SourceasIList;列表NewList=newList();if(Key!=null&&R.ContainsKey(Key)){//已经存在,覆盖NewList=(List)R[Key];}foreach(S中的动态D){ExpandoObjectListEntry=newExpandoObject();DynamicIntoExpando(ListEntry,D);//在这种情况下,我们必须将ListEntry与现有条目进行比较,并在NewList.Add(ListEntry)上进行比较;}if(Key!=null&&!R.ContainsKey(Key)){R[Key]=NewList.Distinct().ToList();}}else{R[Key]=来源;}}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如有转载请注明出处:
