如何解析C#泛型类型名称?分享
时间:2023-04-10 18:53:12
C#
如何解析C#泛型类型名?如何解析格式为List或Dictionary或更复杂的Dictionary的C#样式泛型类型名称。这些名称被假定为字符串,实际上可能不代表现有类型。解析BogusClass应该很容易。要清楚List`1[[System.Int32]],我对解析List`1[[System.Int32]]形式的.NET内部类型名称不感兴趣,但对出现的实际C#类型名称感兴趣在源代码兴趣中,带点或不带命名空间限定符符号。正则表达式,因为它们是嵌套结构。我想也许System.CodeDom.CodeTypeReference构造函数会为我解析它,因为它有字符串BaseType和CodeTypeReferenceCollectionTypeArguments成员,但这些显然需要手动设置。CodeTypeReference是我需要的结构:classTypeNameStructure{publicstringName;publicTypeNameStructure[]GenericTypeArguments;publicboolIsGenericType{get;}publicboolIsArray{get;}//也可以很好地检测到这一点实现这种类型名称解析的框架?如果没有,我将如何解析这个?回答你自己的问题。我写了下面的课程来达到我需要的结果;试一试。公共类TypeName{公共字符串名称;公共布尔IsGeneric;公共列表ArrayDimensions;公共列表类型参数;公共类ArrayDimension{publicintDimensions;publicArrayDimension(){维度=1;}publicoverridestringToString(){return"["+newString(',',Dimensions-1)+"]";}}publicTypeName(){名称=null;IsGeneric=false;ArrayDimensions=new列表();TypeArguments=new列表();}publicstaticstringMatchStructure(TypeNametoMatch,TypeNametoType){returnnull;}publicoverridestringToString(){stringstr=Name;如果(IsGeneric)str+="(tn=>tn.ToString()))+">";foreach(ArrayDimensions中的ArrayDimensiond)str+=d.ToString();returnstr;}publicstringFormatForDisplay(intindent=0){varspacing=newstring('',indent);stringstr=spacing+"Name:"+Name+"rn"+spacing+"IsGeneric:"+IsGeneric+"rn"+spacing+"ArraySpec:"+string.Join("",ArrayDimensions.Select(d=>d.ToString()))+"rn";if(IsGeneric){str+=spacing+"GenericParameters:{rn"+string.Join(spacing+"},{rn",TypeArguments.Select(t=>t.FormatForDisplay(indent+4)))+spacing+“}rn”;}返回海峡;}publicstaticTypeNameParse(stringname){intpos=0;布尔虚拟;返回ParseInternal(名称,参考位置,虚拟);}privatestaticTypeNameParseInternal(stringname,refintpos,outboollistTerminated){StringBuildersb=newStringBuilder();TypeNametn=newTypeName();listTerminated=true;while(pos':if(tn.Name==null)tn.Name=sb.ToString();listTerminated=true;returntn;case'')continue;elsethrownewException("Missingclosing>ofgenerictypelist.");}case'[':ArrayDimensiond=newArrayDimension();tn.ArrayDimensions.Add(d);analyzeArrayDimension://用于循环多维数组的标签if(pos如果我运行以下内容:Console.WriteLine(TypeName.Parse("System.Collections.Generic.Dictionary,int[],bool>").ToString());正确生成以下输出,将TypeName表示为字符串:Name:System.Collections.Generic.DictionaryIsGeneric:TrueArraySpec:GenericParameters:{Name:VectorIsGeneric:TrueArraySpec:GenericParameters:{Name:TIsGeneric:FalseArraySpec:}},{Name:intIsGeneric:TrueArraySpec:[]GenericParameters:{Name:longIsGeneric:FalseArraySpec:[]}},{Name:bool}IsGeneric:FalseArraySpec:}好吧,我在使用Regex和命名捕获组(?group)编写这个小解析类时玩得很开心我的方法是每个“类型定义”字符串都可以分解为以下组:类型名称,一个可选的泛型类型和一个可选的数组标记'[]'。因此,给定一个经典的字典,您将使用字典作为类型名称和字符串,字节[]作为内部泛型类型字符串。我们可以使用逗号(',')字符,并使用相同的正则表达式递归解析每个类型字符串,每次解析成功都应添加到父类型信息中,并可以构建树状层次结构。在前面的示例中,我们最终得到了一个要解析的{string,byte[]}数组。两者都很容易解析并设置为字典内部类型的一部分。在ToString()中,它只是递归地输出每种类型的友好名称,包括内部类型。所以Dictionary会输出他的类型名,并遍历所有内部类型,输出它们的类型名等等。classTypeInformation{staticreadonlyRegexTypeNameRegex=newRegex(@"^(?[a-zA-Z0-9_]+)([a-zA-Z0-9_,s[]]+)>)?(?([]))?$",RegexOptions.Compiled);只读列表innerTypes=newList();公共字符串类型名称{得到;私有集;}publicboolIsArray{得到;私有集;}publicboolIsGeneric{get{returninnerTypes.Count>0;}}publicIEnumerableInnerTypes{get{returninnerTypes;}}privatevoidAddInnerType(TypeInformationtype){innerTypes.Add(type);}privatestaticIEnumerableSplitByComma(stringvalue){varstrings=newList();varsb=newStringBuilder();变种水平=0;foreach(varcinvalue){if(c==','&&level==0){strings.Add(sb.ToString());sb.Clear();}else{sb.Append(c);}if(c=='')级别--;}strings.Add(sb.ToString());返回字符串;}publicstaticboolTryParse(stringfriendlyTypeName,outTypeInformationtypeInformation){typeInformation=null;//尝试将类型与我们的正则表达式相匹配会话。varmatch=TypeNameRegex.Match(friendlyTypeName);//如果失败,则格式不正确。如果(!match.Success)返回false;//清除类型名称、内部类型名称和数组“[]”标记(如果存在)。vartypeName=match.Groups["TypeName"].Value;varinnerTypeFriendlyName=match.Groups["InnerTypeName"].Value;varisArray=!string.IsNullOrWhiteSpace(match.Groups["Array"].Value);//创建根类型信息。TypeInformationtype=newTypeInformation{TypeName=typeName,IsArray=isArray};//检查我们是否有内部类型名称(在泛型的情况下)。if(!string.IsNullOrWhiteSpace(innerTypeFriendlyName)){//用逗号分隔每个类型。varinnerTypeNames=SplitByComma(innerTypeFriendlyName);//遍历所有内部类型名称并尝试递归解析它们。foreach(innerTypeNames中的字符串innerTypeName){TypeInformationinnerType=null;vartrimmedInnerTypeName=innerTypeName.Trim();变量success=TypeInformation.TryParse(trimmedInnerTypeName,outinnerType);//如果内部类型失败,父类型也会失败。如果(!成功)返回假;//成功!将内部类型添加到父级。type.AddInnerType(innerType);}}//返回解析后的类型信息。类型信息=类型;返回真;}publicoverridestringToString(){//创建一个带有预填充类型名称的字符串生成器。varsb=newStringBuilder(this.TypeName);//如果此类型是通用的(具有内部类型),则递归地附加每个。如果(这。IsGeneric){某人。附加(””);}//如果这个类型是一个数组,我们附加数组'[]'marker.if(this.IsArray)sb.Append("[]");返回sb.ToString();我做了一个控制台应用程序来测试它,它似乎适用于我抛出的大多数情况这是代码:classMainClass{staticreadonlyintRootIndentLevel=2;静态只读字符串InputString=@"BogusClass>";publicstaticvoidMain(string[]args){TypeInformationtype=null;Console.WriteLine("输入={0}",InputString);varsuccess=TypeInformation.TryParse(InputString,输出类型);如果(成功){Console.WriteLine("Output={0}",type.ToString());Console.WriteLine("图形:");OutputGraph(类型,RootIndentLevel);}elseConsole.WriteLine("解析错误!");}staticvoidOutputGraph(TypeInformationtype,intindentLevel=0){Console.WriteLine("{0}{1}{2}",newstring('',indentLevel),type.TypeName,type.IsArray?"[]“:字符串。空);foreach(varinnerTypeintype.InnerTypes)OutputGraph(innerType,indentLevel+2);这是输出:Input=BogusClass>Output=BogusClass>Graph:BogusClassABVectorC可能存在一些延迟问题,例如多维数组。它很可能会因int[,]或string[][]之类的东西而失败。以上是C#学习教程:如何解析C#泛型类型名?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: