/// <summary> /// Gets the <see cref="FieldInfo"/> as a code gen member (<see cref="CgMember"/>) /// </summary> /// <param name="fi"></param> /// <param name="valueTypeOnly"></param> /// <param name="enumValueDictionary"></param> /// <returns></returns> public static CgMember GetAsCgMember(FieldInfo fi, bool valueTypeOnly, Dictionary <string, string[]> enumValueDictionary) { if (fi == null) { return(null); } if (NfReflect.IsClrGeneratedType(fi.Name)) { return(null); } var fiType = fi.NfFieldType(); if (valueTypeOnly && fiType.NfBaseType() != null && fiType.NfBaseType().Name != VALUE_TYPE) { return(null); } var cgMem = new CgMember { TypeName = Settings.LangStyle.TransformClrTypeSyntax(fiType), IsEnumerableType = NfReflect.IsEnumerableReturnType(fiType), Name = fi.Name, IsStatic = fi.IsStatic, MetadataToken = fi.MetadataToken }; string[] enumVals; if (NfReflect.IsEnumType(fiType, out enumVals) && enumValueDictionary != null) { cgMem.IsEnum = true; var clearName = NfReflect.GetLastTypeNameFromArrayAndGeneric(cgMem.TypeName, "<"); if (!enumValueDictionary.ContainsKey(clearName)) { enumValueDictionary.Add(clearName, enumVals); } } return(cgMem); }
/// <summary> /// Gets a method as a code gen member type /// </summary> /// <param name="mti"></param> /// <param name="getCallvirtMetadataTokens"></param> /// <returns></returns> public static CgMember GetAsCgMember(MethodInfo mti, bool getCallvirtMetadataTokens = false) { if (mti == null) { return(null); } if (NfReflect.IsClrMethodForProperty(mti.Name, out _)) { return(null); } if (NfReflect.IsClrGeneratedType(mti.Name)) { //these appear as '<SomeNameOfMethodAlreadyAdded>b__kifkj(...)' return(null); } var miReturnType = mti.NfReturnType(); var cgMem = new CgMember { Name = mti.Name, TypeName = Settings.LangStyle.TransformClrTypeSyntax(miReturnType), IsStatic = mti.IsStatic, IsGeneric = mti.IsGenericMethod, IsEnumerableType = NfReflect.IsEnumerableReturnType(miReturnType), IsMethod = true, MetadataToken = mti.MetadataToken }; if (mti.IsAssembly) { cgMem.AccessModifier = CgAccessModifier.Assembly; } if (mti.IsFamily) { cgMem.AccessModifier = CgAccessModifier.Family; } if (mti.IsFamilyAndAssembly) { cgMem.AccessModifier = CgAccessModifier.FamilyAssembly; } if (mti.IsPrivate) { cgMem.AccessModifier = CgAccessModifier.Private; } if (mti.IsPublic) { cgMem.AccessModifier = CgAccessModifier.Public; } foreach (var parameterInfo in mti.GetParameters()) { var paramType = parameterInfo.NfParameterType(); var cgArg = new CgArg { ArgName = parameterInfo.Name, ArgType = Settings.LangStyle.TransformClrTypeSyntax(paramType) }; cgMem.Args.Add(cgArg); } cgMem.MethodBodyIL = Convert.ToBase64String(Asm.GetMethodBody(mti)); if (!getCallvirtMetadataTokens) { return(cgMem); } cgMem.opCodeCallsAndCallvirtsMetadatTokens.AddRange(Asm.GetCallsMetadataTokens(mti)); return(cgMem); }
/// <summary> /// Converts the .NET type into the custom Code Gen type /// </summary> /// <param name="asmType"></param> /// <param name="valueTypeOnly"> /// Will only export Fields and Properties whose base type extends System.ValueType /// </param> /// <param name="resolveDependencies"> /// Switch to have the IL of the type parsed and all dependent calls Metadata tokens added. /// </param> /// <returns></returns> public static CgType GetCgOfType(this Type asmType, bool valueTypeOnly, bool resolveDependencies = false) { var cgType = new CgType(); if (asmType == null || NfReflect.IsIgnoreType(asmType) || NfReflect.IsClrGeneratedType(asmType)) { return(null); } //use the logic in TypeName to get the namespace and class name so its not tied to having the assembly var cgTypeName = new NfTypeName(asmType.AssemblyQualifiedName); //make sure there is always some kind of namespace cgType.Namespace = string.IsNullOrWhiteSpace(cgTypeName.Namespace) ? asmType.Assembly.GetName().Name : cgTypeName.Namespace; cgType.IsContrivedNamespace = string.IsNullOrWhiteSpace(cgTypeName.Namespace); cgType.Name = cgTypeName.ClassName; cgType.AssemblyQualifiedName = asmType.AssemblyQualifiedName; cgType.IsEnum = NfReflect.IsEnumType(asmType); var cgTypesInterfaces = asmType.GetInterfaces(); cgType.MetadataToken = asmType.MetadataToken; Func <CgType, string, bool> alreadyPresentHerein = (cg, nextName) => (cg.Properties.FirstOrDefault( cgP => string.Equals(cgP.Name, nextName, StringComparison.OrdinalIgnoreCase)) != null || cg.Fields.FirstOrDefault( cgF => string.Equals(cgF.Name, nextName, StringComparison.OrdinalIgnoreCase)) != null || cg.Events.FirstOrDefault( cgE => string.Equals(cgE.Name, nextName, StringComparison.OrdinalIgnoreCase)) != null) ; //have events go first since they tend to be speard across fields and properties foreach ( var evtInfo in asmType.GetEvents(Shared.Core.NfSettings.DefaultFlags)) { var evtHandlerType = evtInfo.NfEventHandlerType().ToString(); var cgMem = new CgMember { Name = evtInfo.Name, TypeName = evtHandlerType, MetadataToken = evtInfo.MetadataToken }; cgType.Events.Add(cgMem); } var asmMembers = asmType.GetMembers(Shared.Core.NfSettings.DefaultFlags); foreach (var mi in asmMembers) { if (alreadyPresentHerein(cgType, mi.Name)) { continue; } try { if (mi.MemberType == MemberTypes.Property) { var pi = mi as PropertyInfo; var cgm = GetAsCgMember(pi, valueTypeOnly, cgType.EnumValueDictionary); if (cgm == null) { continue; } if (resolveDependencies) { var propMi = NfReflect.GetMethodsForProperty(pi, asmType); foreach (var pim in propMi) { cgm.opCodeCallsAndCallvirtsMetadatTokens.AddRange(Asm.GetCallsMetadataTokens(pim)); } } cgType.Properties.Add(cgm); } } catch (Exception ex) { Asm.AddLoaderExceptionToLog(null, ex); if (!Settings.IgnoreReflectionMissingAsmError) { throw; } cgType.Properties.Add(new CgMember { Name = mi.Name, TypeName = DF_TYPE_NAME, HasGetter = true, HasSetter = true, SkipIt = true }); } try { if (mi.MemberType == MemberTypes.Event) { continue;//these have already been handled } } catch (Exception ex) { Asm.AddLoaderExceptionToLog(null, ex); continue; } try { if (mi.MemberType == MemberTypes.Field) { var fi = mi as FieldInfo; var cgm = GetAsCgMember(fi, valueTypeOnly, cgType.EnumValueDictionary); if (cgm == null) { continue; } cgType.Fields.Add(cgm); } } catch (Exception ex) { Asm.AddLoaderExceptionToLog(null, ex); if (!Settings.IgnoreReflectionMissingAsmError) { throw; } cgType.Fields.Add(new CgMember { Name = mi.Name, TypeName = DF_TYPE_NAME, SkipIt = true }); } try { if (!valueTypeOnly && mi.MemberType == MemberTypes.Method) { var mti = mi as MethodInfo; var cgm = GetAsCgMember(mti, resolveDependencies); if (cgm == null) { continue; } cgm.IsInterfaceImpl = IsInterfaceImpl(mti, cgTypesInterfaces); cgType.Methods.Add(cgm); } if (!valueTypeOnly && mi.MemberType == MemberTypes.Constructor) { var ci = mi as ConstructorInfo; var tn = (string.IsNullOrWhiteSpace(cgTypeName.Namespace) ? cgTypeName.ClassName : $"{cgTypeName.Namespace}.{cgTypeName.ClassName}"); var cgm = GetAsCgMember(ci, tn, resolveDependencies); if (cgm == null) { continue; } cgType.Methods.Add(cgm); } } catch (Exception ex) { Asm.AddLoaderExceptionToLog(null, ex); if (!Settings.IgnoreReflectionMissingAsmError) { throw; } cgType.Methods.Add(new CgMember { Name = mi.Name, TypeName = DF_TYPE_NAME, SkipIt = true }); } } if (resolveDependencies) { ResolveAllMetadataTokens(cgType, asmType.Assembly.ManifestModule); } return(cgType); }