private TypeReference SetCachedType(Type type, TypeReference typeRef, GenericImportKind importKind) { if (importKind == GenericImportKind.Definition) { return(typeRef); } return(CachedTypes[type] = typeRef); }
private bool TryGetCachedType(Type type, out TypeReference typeRef, GenericImportKind importKind) { if (importKind == GenericImportKind.Definition) { typeRef = null; return(false); } return(CachedTypes.TryGetValue(type, out typeRef)); }
private MethodReference _ImportReference(MethodBase method, IGenericParameterProvider context, GenericImportKind importKind) { if (CachedMethods.TryGetValue(method, out MethodReference methodRef) && importKind == GenericImportKind.Open) { return(methodRef); } if (method is DynamicMethod dm) { return(new DynamicMethodReference(Module, dm)); } if (UseDefault) { return(CachedMethods[method] = Default.ImportReference(method, context)); } if (method.IsGenericMethod && !method.IsGenericMethodDefinition || method.IsGenericMethod && method.IsGenericMethodDefinition && importKind == GenericImportKind.Open) { GenericInstanceMethod gim = new GenericInstanceMethod(_ImportReference((method as MethodInfo).GetGenericMethodDefinition(), context, GenericImportKind.Definition)); foreach (Type arg in method.GetGenericArguments()) { // Generic arguments for the generic instance are often given by the next higher provider. gim.GenericArguments.Add(_ImportReference(arg, context)); } return(CachedMethods[method] = gim); } Type declType = method.DeclaringType; methodRef = new MethodReference( method.Name, _ImportReference(typeof(void), context), declType != null ? _ImportReference(declType, context, GenericImportKind.Definition) : ImportModuleType(method.Module, context) ); methodRef.HasThis = (method.CallingConvention & CallingConventions.HasThis) != 0; methodRef.ExplicitThis = (method.CallingConvention & CallingConventions.ExplicitThis) != 0; if ((method.CallingConvention & CallingConventions.VarArgs) != 0) { methodRef.CallingConvention = MethodCallingConvention.VarArg; } MethodBase methodOrig = method; if (declType != null && declType.IsGenericType) { // In methods of generic types, all generic parameters are already filled in. // Meanwhile, cecil requires generic parameter references. // Luckily the metadata tokens match up. method = method.Module.ResolveMethod(method.MetadataToken); } if (method.IsGenericMethodDefinition) { foreach (Type param in method.GetGenericArguments()) { methodRef.GenericParameters.Add(new GenericParameter(param.Name, methodRef)); } } methodRef.ReturnType = _ImportReference((method as MethodInfo)?.ReturnType ?? typeof(void), methodRef); foreach (ParameterInfo param in method.GetParameters()) { methodRef.Parameters.Add(new ParameterDefinition( param.Name, (Mono.Cecil.ParameterAttributes)param.Attributes, _ImportReference(param.ParameterType, methodRef) )); } return(CachedMethods[methodOrig] = methodRef); }
private TypeReference _ImportReference(Type type, IGenericParameterProvider context, GenericImportKind importKind = GenericImportKind.Open) { if (TryGetCachedType(type, out TypeReference typeRef, importKind)) { return(_IsGenericInstance(type, importKind) ? _ImportGenericInstance(type, context, typeRef) : typeRef); } if (UseDefault) { return(SetCachedType(type, Default.ImportReference(type, context), importKind)); } if (type.HasElementType) { if (type.IsByRef) { return(SetCachedType(type, new ByReferenceType(_ImportReference(type.GetElementType(), context)), importKind)); } if (type.IsPointer) { return(SetCachedType(type, new PointerType(_ImportReference(type.GetElementType(), context)), importKind)); } if (type.IsArray) { ArrayType at = new ArrayType(_ImportReference(type.GetElementType(), context), type.GetArrayRank()); if (type != type.GetElementType().MakeArrayType()) { // Non-SzArray // TODO: Find a way to get the bounds without instantiating the array type! /* * Array a = Array.CreateInstance(type, new int[type.GetArrayRank()]); * if ( * at.Rank > 1 * && a.IsFixedSize * ) { * for (int i = 0; i < at.Rank; i++) * at.Dimensions[i] = new ArrayDimension(a.GetLowerBound(i), a.GetUpperBound(i)); * } */ // For now, always assume [0...,0..., // Array.CreateInstance only accepts lower bounds anyway. for (int i = 0; i < at.Rank; i++) { at.Dimensions[i] = new ArrayDimension(0, null); } } return(CachedTypes[type] = at); } } if (_IsGenericInstance(type, importKind)) { return(_ImportGenericInstance(type, context, _ImportReference(type.GetGenericTypeDefinition(), context, GenericImportKind.Definition))); } if (type.IsGenericParameter) { return(SetCachedType(type, ImportGenericParameter(type, context), importKind)); } if (ElementTypes.TryGetValue(type, out typeRef)) { return(SetCachedType(type, typeRef, importKind)); } typeRef = new TypeReference( string.Empty, type.Name, Module, ImportReference(type.Assembly.GetName()), type.IsValueType ); if (type.IsNested) { typeRef.DeclaringType = _ImportReference(type.DeclaringType, context, importKind); } else if (type.Namespace != null) { typeRef.Namespace = type.Namespace; } if (type.IsGenericType) { foreach (Type param in type.GetGenericArguments()) { typeRef.GenericParameters.Add(new GenericParameter(param.Name, typeRef)); } } return(SetCachedType(type, typeRef, importKind)); }
private bool _IsGenericInstance(Type type, GenericImportKind importKind) { return(type.IsGenericType && !type.IsGenericTypeDefinition || type.IsGenericType && type.IsGenericTypeDefinition && importKind == GenericImportKind.Open); }