| |
| |
| |
| public static class NotifyTypeEmit |
| { |
| public static T CreateInstance<T>() |
| { |
| return (T)CreateInstance(typeof(T)); |
| } |
| public static object CreateInstance(Type baseType) |
| { |
| var type = CreateType(baseType); |
| return Activator.CreateInstance(type); |
| } |
| |
| |
| |
| |
| |
| |
| |
| public static Type CreateType(Type baseType) |
| { |
| if (!s_extensionTypes.ContainsKey(baseType)) |
| { |
| var type = _CreateType(baseType); |
| s_extensionTypes.TryAdd(baseType, type); |
| } |
| |
| return s_extensionTypes[baseType]; |
| } |
| |
| private static ConcurrentDictionary<Type, Type> s_extensionTypes |
| = new ConcurrentDictionary<Type, Type>(); |
| |
| |
| private static Type _CreateType(Type baseType) |
| { |
| var assemblyName = new AssemblyName("TrykleMvvmToolkit.NotifyTypeEmit.Assembly"); |
| |
| |
| var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); |
| var moduleBuilder = assemblyBuilder.DefineDynamicModule("TrykleMvvmToolkit.NotifyTypeEmit.Module", "NortiyTypeEmit_Test.dll"); |
| |
| var typeBuilder = moduleBuilder.DefineType($"{baseType.Name}_EXTENSION", TypeAttributes.Public | TypeAttributes.Class, baseType, new[] { typeof(INotifyPropertyChanged) }); |
| |
| var eventBuilder = typeBuilder.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler)); |
| var eventFieldBuilder = typeBuilder.DefineField("PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Private); |
| |
| var interfaceMethodInfo = typeof(INotifyPropertyChanged).GetMethod("add_PropertyChanged"); |
| var addMethod = typeBuilder.DefineMethod(interfaceMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual, typeof(void), new Type[] { typeof(PropertyChangedEventHandler) }); |
| var ilAddMethod = addMethod.GetILGenerator(); |
| ilAddMethod.Emit(OpCodes.Ldarg_0); |
| ilAddMethod.Emit(OpCodes.Ldarg_0); |
| ilAddMethod.Emit(OpCodes.Ldfld, eventFieldBuilder); |
| ilAddMethod.Emit(OpCodes.Ldarg_1); |
| ilAddMethod.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Combine", new Type[] { typeof(Delegate), typeof(Delegate) })); |
| ilAddMethod.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler)); |
| ilAddMethod.Emit(OpCodes.Stfld, eventFieldBuilder); |
| ilAddMethod.Emit(OpCodes.Ret); |
| typeBuilder.DefineMethodOverride(addMethod, interfaceMethodInfo); |
| eventBuilder.SetAddOnMethod(addMethod); |
| |
| interfaceMethodInfo = typeof(INotifyPropertyChanged).GetMethod("remove_PropertyChanged"); |
| var removeMethod = typeBuilder.DefineMethod(interfaceMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual, typeof(void), new Type[] { typeof(PropertyChangedEventHandler) }); |
| var ilRemoveMethod = removeMethod.GetILGenerator(); |
| ilRemoveMethod.Emit(OpCodes.Ldarg_0); |
| ilRemoveMethod.Emit(OpCodes.Ldarg_0); |
| ilRemoveMethod.Emit(OpCodes.Ldfld, eventFieldBuilder); |
| ilRemoveMethod.Emit(OpCodes.Ldarg_1); |
| ilRemoveMethod.Emit(OpCodes.Call, typeof(Delegate).GetMethod("Remove", new Type[] { typeof(Delegate), typeof(Delegate) })); |
| ilRemoveMethod.Emit(OpCodes.Castclass, typeof(PropertyChangedEventHandler)); |
| ilRemoveMethod.Emit(OpCodes.Stfld, eventFieldBuilder); |
| ilRemoveMethod.Emit(OpCodes.Ret); |
| typeBuilder.DefineMethodOverride(removeMethod, interfaceMethodInfo); |
| eventBuilder.SetRemoveOnMethod(removeMethod); |
| |
| foreach (var propertyInfo in baseType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) |
| { |
| if (propertyInfo.GetGetMethod() == null || (propertyInfo.GetSetMethod() == null)) |
| { |
| continue; |
| } |
| var propertyName = propertyInfo.Name; |
| var getPropertyName = $"get_{propertyName}"; |
| var setPropertyName = $"set_{propertyName}"; |
| var propertyType = propertyInfo.PropertyType; |
| |
| var propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null); |
| var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual; |
| |
| var getterMethodBuilder = typeBuilder.DefineMethod(getPropertyName, methodAttributes, propertyType, Type.EmptyTypes); |
| var getterIL = getterMethodBuilder.GetILGenerator(); |
| getterIL.Emit(OpCodes.Ldarg_0); |
| getterIL.Emit(OpCodes.Call, baseType.GetProperty(propertyName).GetGetMethod()); |
| getterIL.Emit(OpCodes.Ret); |
| propertyBuilder.SetGetMethod(getterMethodBuilder); |
| |
| var setterMethodBuilder = typeBuilder.DefineMethod(setPropertyName, methodAttributes, null, new[] { propertyType }); |
| var setterIL = setterMethodBuilder.GetILGenerator(); |
| setterIL.Emit(OpCodes.Ldarg_0); |
| setterIL.Emit(OpCodes.Ldarg_1); |
| setterIL.Emit(OpCodes.Call, baseType.GetProperty(propertyName).GetSetMethod()); |
| setterIL.Emit(OpCodes.Ldarg_0); |
| setterIL.Emit(OpCodes.Ldfld, eventFieldBuilder); |
| var label = setterIL.DefineLabel(); |
| setterIL.Emit(OpCodes.Brfalse_S, label); |
| setterIL.Emit(OpCodes.Ldarg_0); |
| setterIL.Emit(OpCodes.Ldfld, eventFieldBuilder); |
| setterIL.Emit(OpCodes.Ldarg_0); |
| setterIL.Emit(OpCodes.Ldstr, propertyName); |
| setterIL.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs).GetConstructor(new[] { typeof(string) }) |
| ); |
| setterIL.Emit(OpCodes.Callvirt, typeof(PropertyChangedEventHandler).GetMethod("Invoke")); |
| setterIL.MarkLabel(label); |
| setterIL.Emit(OpCodes.Ret); |
| propertyBuilder.SetSetMethod(setterMethodBuilder); |
| } |
| |
| |
| typeBuilder.CreateType(); |
| assemblyBuilder.Save("NortiyTypeEmit_Test.dll"); |
| return typeBuilder; |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-08-08 Maxscript 画个桃心