private static ResourceRecord GetResource(Type type) { if (type == null) { throw new ArgumentNullException("type"); } ResourceRecord result; if (_impls.TryGetValue(type, out result)) { return(result); } var assemblyName = new AssemblyName { Name = "tmp_" + type.Name }; var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var module = assemblyBuilder.DefineDynamicModule("tmpModule"); var typeBuilder = module.DefineType(type.Name + "SharedSingletonWrapper", TypeAttributes.Public | TypeAttributes.Class, type); var baseDispose = type.GetMethod("Dispose", BindingFlags.Public | BindingFlags.Instance); if (baseDispose.IsFinal) { throw new Exception(type.Name + ".Dispose() is final"); } var disposeFun = typeBuilder.DefineMethod("Dispose", MethodAttributes.Virtual | MethodAttributes.Public, typeof(void), Type.EmptyTypes); var disposeBaseFun = typeBuilder.DefineMethod("DisposeBase", MethodAttributes.Public, typeof(void), Type.EmptyTypes); typeBuilder.DefineField("key", typeof(AllocationKey), FieldAttributes.Public); var ilDispose = disposeFun.GetILGenerator(); var release = ReflectionMarkerAttribute.FindMethod( typeof(ResourceManager), ReflectionToken.ResourceHelperRelease); ilDispose.Emit(OpCodes.Ldarg, 0); ilDispose.Emit(OpCodes.Call, release); ilDispose.Emit(OpCodes.Ret); var ilDisposeBase = disposeBaseFun.GetILGenerator(); ilDisposeBase.Emit(OpCodes.Ldarg, 0); ilDisposeBase.Emit(OpCodes.Call, type.GetMethod("Dispose", BindingFlags.Public | BindingFlags.Instance)); ilDisposeBase.Emit(OpCodes.Ret); foreach (var tctor in type.GetConstructors(BindingFlagsAny)) { if (tctor.IsPrivate) { continue; } // create a default ctor for T' var tparams = tctor.GetParameters(); var nparams = new Type[tparams.Length]; for (var i = 0; i < tparams.Length; i++) { nparams[i] = tparams[i].ParameterType; } var ttctor = typeBuilder.DefineConstructor(MethodAttributes.Public, tctor.CallingConvention, nparams); var cil = ttctor.GetILGenerator(); for (var i = 0; i < tparams.Length + 1; i++) { cil.Emit(OpCodes.Ldarg, i); } cil.Emit(OpCodes.Call, tctor); cil.Emit(OpCodes.Ret); } result = new ResourceRecord { Implementation = typeBuilder.CreateType() }; _impls[type] = result; return(result); }
/// <summary> /// Reflection utility that implements a shader around any user defined shader. /// Creating code for any uniform defined. /// </summary> /// <param name="type">The shader type to derive from</param> /// <returns>A constructor to the derived type</returns> private static ConstructorInfo GetConstructor(Type type) { var baseBegin = ReflectionMarkerAttribute.FindMethod( typeof(Shader), ReflectionToken.ShaderBegin); if (type.IsNotPublic) { throw new Exception("Type " + type.Name + " must be public"); } ConstructorInfo ctor; if (_ctors.TryGetValue(type, out ctor)) { try { return(ctor); } catch (Exception e) { throw e.InnerException; } } var assemblyName = new AssemblyName { Name = "tmp_" + type.Name }; var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var module = assemblyBuilder.DefineDynamicModule("tmpModule"); var typeBuilder = module.DefineType(type.Name + "_impl", TypeAttributes.Public | TypeAttributes.Class, type); var beginFun = typeBuilder.DefineMethod(baseBegin.Name, MethodAttributes.Virtual | MethodAttributes.Public, typeof(void), Type.EmptyTypes); var ilBeg = beginFun.GetILGenerator(); var getName = ReflectionMarkerAttribute.FindProperty( typeof(Shader), ReflectionToken.ShaderName).GetGetMethod(); var nameIndex = ilBeg.DeclareLocal(typeof(IProgram)).LocalIndex; var shaderActivate = ReflectionMarkerAttribute.FindMethod( typeof(Shader), ReflectionToken.ShaderActivate); ilBeg.Emit(OpCodes.Ldarg, 0); ilBeg.Emit(OpCodes.Call, shaderActivate); ilBeg.Emit(OpCodes.Ldarg, 0); ilBeg.Emit(OpCodes.Call, getName); ilBeg.Emit(OpCodes.Stloc, nameIndex); foreach (var prop in type.GetProperties(BindingFlagsAny)) { var attr = prop.GetCustomAttributes(typeof(UniformAttribute), false); if (attr.Length == 0) { continue; } var info = TypeMap[prop.PropertyType.MetadataToken]; var uniformCall = Binding.Resolve(info.Token); var f = typeBuilder.DefineField("m_" + prop.Name, typeof(int), FieldAttributes.Private); //var visibility = prop.PropertyType.IsPublic ? MethodAttributes.Public : MethodAttributes.Family; const MethodAttributes visibility = MethodAttributes.Public; var getter = prop.GetSetMethod() != null?prop.GetGetMethod().Name : "get_" + prop.Name; var setter = prop.GetSetMethod() != null?prop.GetSetMethod().Name : "set_" + prop.Name; var m = typeBuilder.DefineMethod(setter, MethodAttributes.Virtual | visibility, typeof(void), new[] { prop.PropertyType }); var ilg = m.GetILGenerator(); ilg.Emit(OpCodes.Ldarg, 0); ilg.Emit(OpCodes.Ldfld, f); if (uniformCall.GetParameters().Length == 2) { ilg.Emit(OpCodes.Ldarg, 1); } ilg.Emit(OpCodes.Call, uniformCall); ilg.Emit(OpCodes.Ret); m = typeBuilder.DefineMethod(getter, MethodAttributes.Virtual | visibility, prop.PropertyType, Type.EmptyTypes); ilg = m.GetILGenerator(); ilg.Emit(OpCodes.Newobj, typeof(NotImplementedException)); ilg.Emit(OpCodes.Throw); } ilBeg.Emit(OpCodes.Ldarg, 0); ilBeg.Emit(OpCodes.Call, type.GetMethod(baseBegin.Name, Type.EmptyTypes)); ilBeg.Emit(OpCodes.Ret); // implement in accessors foreach (var prop in type.GetProperties(BindingFlagsAny)) { var attr = prop.GetCustomAttributes(typeof(VertexInAttribute), false); if (attr.Length == 0) { continue; } var getter = prop.GetSetMethod() != null?prop.GetGetMethod().Name : "get_" + prop.Name; var setter = prop.GetSetMethod() != null?prop.GetSetMethod().Name : "set_" + prop.Name; //var visibility = prop.PropertyType.IsPublic ? MethodAttributes.Public : MethodAttributes.Family; const MethodAttributes visibility = MethodAttributes.Public; var m = typeBuilder.DefineMethod(setter, MethodAttributes.Virtual | visibility, typeof(void), new[] { prop.PropertyType }); var ilg = m.GetILGenerator(); ilg.Emit(OpCodes.Newobj, typeof(NotImplementedException)); ilg.Emit(OpCodes.Throw); m = typeBuilder.DefineMethod(getter, MethodAttributes.Virtual | visibility, prop.PropertyType, Type.EmptyTypes); ilg = m.GetILGenerator(); ilg.Emit(OpCodes.Newobj, typeof(NotImplementedException)); ilg.Emit(OpCodes.Throw); } var timpl = typeBuilder.CreateType(); ctor = timpl.GetConstructor(Type.EmptyTypes); _ctors[type] = ctor; return(ctor); }