public static Type Merge(params Type[] types) { if (!types.All(t => t.IsInterface)) { throw new ArgumentException("One or more provided types are not an interface."); } var name = $"dynMerge({RandomEx.GetString(ranLength)})_" + String.Join("_", types.Select(t => t.Name)); var typeBuilder = modBuilder.DefineType( name, TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract); foreach (Type t in types) { typeBuilder.AddInterfaceImplementation(t); } return(typeBuilder.CreateType()); }
public GenericMemoryCache() { _internal = new MemoryCache(typeof(TValue).Name + "_" + RandomEx.GetString(8)); }
private static Type CreateImplementerType(Type target, DynamicInterfaceMethodHandler implementer) { if (!target.IsInterface) { throw new ArgumentException("target must be an interface type."); } var name = $"dynImplement({RandomEx.GetString(ranLength)})_" + target.Name; var typeBuilder = modBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Class); typeBuilder.AddInterfaceImplementation(target); var implementerField = typeBuilder.DefineField("_implementer", typeof(DynamicInterfaceMethodHandler), FieldAttributes.Private); var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, new Type[] { typeof(DynamicInterfaceMethodHandler) }); // emit constructor var constructorIl = constructorBuilder.GetILGenerator(); constructorIl.Emit(OpCodes.Ldarg_0); constructorIl.Emit(OpCodes.Ldarg_1); constructorIl.Emit(OpCodes.Stfld, implementerField); constructorIl.Emit(OpCodes.Ret); string debugPath = null; ISymbolDocumentWriter doc = null; if (emitSymbols) { debugPath = Path.GetTempFileName(); doc = modBuilder.DefineDocument(debugPath, Guid.Empty, Guid.Empty, Guid.Empty); } // implement all interface methods. Dictionary <string, MethodBuilder> builders = new Dictionary <string, MethodBuilder>(); var methods = target.GetMethods().Concat(target.GetInterfaces().SelectMany(inter => inter.GetMethods())); foreach (var method in methods) { if (emitSymbols) { File.AppendAllText(debugPath, ".method " + method.Name + Environment.NewLine); } var methodParamaters = method.GetParameters().Select(p => p.ParameterType).ToArray(); var methodBuilder = typeBuilder.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.CallingConvention, method.ReturnType, methodParamaters); builders[method.Name] = methodBuilder; var methodIl = emitSymbols ? (ILGeneratorInterface) new DebuggableILGenerator(methodBuilder.GetILGenerator(), doc, debugPath) : new StandardILGenerator(methodBuilder.GetILGenerator()); var objLocalIndex = methodIl.DeclareLocal(typeof(object[])).LocalIndex; var retIsOk = methodIl.DefineLabel(); // create new object[] to hold paramaters and store it to local methodIl.Emit(OpCodes.Ldc_I4, methodParamaters.Length); methodIl.Emit(OpCodes.Newarr, typeof(object)); methodIl.Emit(OpCodes.Stloc, objLocalIndex); // fill object array with method parameters for (int i = 0; i < methodParamaters.Length; i++) { methodIl.Emit(OpCodes.Ldloc, objLocalIndex); methodIl.Emit(OpCodes.Ldc_I4, i); methodIl.Emit(OpCodes.Ldarg, i + 1); if (methodParamaters[i].IsValueType) { methodIl.Emit(OpCodes.Box, methodParamaters[i]); } methodIl.Emit(OpCodes.Stelem_Ref); } // load current delegate, MethodInfo and object array to the stack methodIl.Emit(OpCodes.Ldarg_0); methodIl.Emit(OpCodes.Ldfld, implementerField); methodIl.Emit(OpCodes.Ldtoken, method); methodIl.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) })); methodIl.Emit(OpCodes.Castclass, typeof(MethodInfo)); methodIl.Emit(OpCodes.Ldloc, objLocalIndex); // call it. methodIl.Emit(method.IsFinal ? OpCodes.Call : OpCodes.Callvirt, typeof(DynamicInterfaceMethodHandler).GetMethod("Invoke")); // handle return type mismatches. if (method.ReturnType == typeof(void)) { methodIl.Emit(OpCodes.Ldnull); // if the last two stack elements are equal (ldnull and delegate result) goto return statement. methodIl.Emit(OpCodes.Beq, retIsOk); // else throw exception methodIl.Emit(OpCodes.Ldstr, "Method return type mismatch: The implementing dynamic delegate tried to return a non-null value, " + "when the actual return value is void."); methodIl.Emit(OpCodes.Newobj, typeof(TargetException).GetConstructor(new Type[] { typeof(string) })); methodIl.Emit(OpCodes.Throw); } else { // check the value for null, if its null just return it methodIl.Emit(OpCodes.Dup); methodIl.Emit(OpCodes.Ldnull); methodIl.Emit(OpCodes.Beq, retIsOk); methodIl.Emit(OpCodes.Dup); methodIl.Emit(OpCodes.Callvirt, typeof(object).GetMethod("GetType", BindingFlags.Instance | BindingFlags.Public)); methodIl.EmitType(method.ReturnType, false); // if the last two stack elements are equal (getType result and the returntype) goto return statement methodIl.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("Equals", new Type[] { typeof(Type) })); methodIl.Emit(OpCodes.Ldc_I4_1); methodIl.Emit(OpCodes.Beq, retIsOk); methodIl.Emit(OpCodes.Ldstr, "Method return type mismatch: The implementing dynamic delegate tried to return a type that does not " + "match the return type of this method."); methodIl.Emit(OpCodes.Newobj, typeof(TargetException).GetConstructor(new Type[] { typeof(string) })); methodIl.Emit(OpCodes.Throw); } methodIl.MarkLabel(retIsOk); if (method.ReturnType.IsValueType && method.ReturnType != typeof(void)) { methodIl.Emit(OpCodes.Unbox_Any, method.ReturnType); } methodIl.Emit(OpCodes.Ret); } // create properties and match them up to appropriate methods. var properties = target.GetProperties().Concat(target.GetInterfaces().SelectMany(inter => inter.GetProperties())); foreach (var prop in properties) { var property = typeBuilder.DefineProperty(prop.Name, PropertyAttributes.HasDefault, prop.PropertyType, Type.EmptyTypes); if (builders.ContainsKey("get_" + prop.Name)) { property.SetGetMethod(builders["get_" + prop.Name]); } if (builders.ContainsKey("set_" + prop.Name)) { property.SetSetMethod(builders["set_" + prop.Name]); } } return(typeBuilder.CreateType()); }