diff --git a/IPA.Loader/Config/Stores/GeneratedStoreImpl/MakeCreator.cs b/IPA.Loader/Config/Stores/GeneratedStoreImpl/MakeCreator.cs index a16c87fe..58aa88a7 100644 --- a/IPA.Loader/Config/Stores/GeneratedStoreImpl/MakeCreator.cs +++ b/IPA.Loader/Config/Stores/GeneratedStoreImpl/MakeCreator.cs @@ -145,139 +145,164 @@ namespace IPA.Config.Stores MethodBuilder notifyChanged = null; if (isINotifyPropertyChanged || hasNotifyAttribute) { - var INotifyPropertyChanged_t = typeof(INotifyPropertyChanged); - typeBuilder.AddInterfaceImplementation(INotifyPropertyChanged_t); - - var INotifyPropertyChanged_PropertyChanged = - INotifyPropertyChanged_t.GetEvent(nameof(INotifyPropertyChanged.PropertyChanged)); - - var PropertyChangedEventHandler_t = typeof(PropertyChangedEventHandler); - var PropertyChangedEventHander_Invoke = PropertyChangedEventHandler_t.GetMethod(nameof(PropertyChangedEventHandler.Invoke)); - - var PropertyChangedEventArgs_t = typeof(PropertyChangedEventArgs); - var PropertyChangedEventArgs_ctor = PropertyChangedEventArgs_t.GetConstructor(new[] { typeof(string) }); - - var Delegate_t = typeof(Delegate); - var Delegate_Combine = Delegate_t.GetMethod(nameof(Delegate.Combine), BindingFlags.Static | BindingFlags.Public, null, - new[] { Delegate_t, Delegate_t }, Array.Empty()); - var Delegate_Remove = Delegate_t.GetMethod(nameof(Delegate.Remove), BindingFlags.Static | BindingFlags.Public, null, - new[] { Delegate_t, Delegate_t }, Array.Empty()); - - var CompareExchange = typeof(Interlocked).GetMethods() - .Where(m => m.Name == nameof(Interlocked.CompareExchange)) - .Where(m => m.ContainsGenericParameters) - .Where(m => m.GetParameters().Length == 3).First() - .MakeGenericMethod(PropertyChangedEventHandler_t); - - var basePropChangedEvent = type.GetEvents() - .Where(e => e.GetAddMethod().GetBaseDefinition().DeclaringType == INotifyPropertyChanged_t) - .FirstOrDefault(); - var basePropChangedAdd = basePropChangedEvent?.GetAddMethod(); - var basePropChangedRemove = basePropChangedEvent?.GetRemoveMethod(); - - var PropertyChanged_backing = typeBuilder.DefineField("PropertyChanged", PropertyChangedEventHandler_t, FieldAttributes.Private); + if (isINotifyPropertyChanged) + { + var ExistingRaisePropertyChanged = type.GetMethod("RaisePropertyChanged", (BindingFlags)int.MaxValue, null, new Type[] { typeof(string) }, Array.Empty()); + if (ExistingRaisePropertyChanged != null) + { + notifyChanged = typeBuilder.DefineMethod("<>NotifyChanged", + MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final, null, new[] { typeof(string) }); - var add_PropertyChanged = typeBuilder.DefineMethod("PropertyChanged", - MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual, - null, new[] { PropertyChangedEventHandler_t }); - typeBuilder.DefineMethodOverride(add_PropertyChanged, INotifyPropertyChanged_PropertyChanged.GetAddMethod()); - if (basePropChangedAdd != null) - typeBuilder.DefineMethodOverride(add_PropertyChanged, basePropChangedAdd); + { + var il = notifyChanged.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Call, ExistingRaisePropertyChanged); + il.Emit(OpCodes.Ret); + } + } + else + { + Logger.log.Critical($"Type '{type.FullName}' implements INotifyPropertyChanged but does not have a 'RaisePropertyChanged(string)' method, automatic raising of PropertyChanged event is disabled."); + } + } + else { - var il = add_PropertyChanged.GetILGenerator(); + var INotifyPropertyChanged_t = typeof(INotifyPropertyChanged); + typeBuilder.AddInterfaceImplementation(INotifyPropertyChanged_t); + + var INotifyPropertyChanged_PropertyChanged = + INotifyPropertyChanged_t.GetEvent(nameof(INotifyPropertyChanged.PropertyChanged)); + + var PropertyChangedEventHandler_t = typeof(PropertyChangedEventHandler); + var PropertyChangedEventHander_Invoke = PropertyChangedEventHandler_t.GetMethod(nameof(PropertyChangedEventHandler.Invoke)); + + var PropertyChangedEventArgs_t = typeof(PropertyChangedEventArgs); + var PropertyChangedEventArgs_ctor = PropertyChangedEventArgs_t.GetConstructor(new[] { typeof(string) }); + + var Delegate_t = typeof(Delegate); + var Delegate_Combine = Delegate_t.GetMethod(nameof(Delegate.Combine), BindingFlags.Static | BindingFlags.Public, null, + new[] { Delegate_t, Delegate_t }, Array.Empty()); + var Delegate_Remove = Delegate_t.GetMethod(nameof(Delegate.Remove), BindingFlags.Static | BindingFlags.Public, null, + new[] { Delegate_t, Delegate_t }, Array.Empty()); + + var CompareExchange = typeof(Interlocked).GetMethods() + .Where(m => m.Name == nameof(Interlocked.CompareExchange)) + .Where(m => m.ContainsGenericParameters) + .Where(m => m.GetParameters().Length == 3).First() + .MakeGenericMethod(PropertyChangedEventHandler_t); + + var basePropChangedEvent = type.GetEvents() + .Where(e => e.GetAddMethod().GetBaseDefinition().DeclaringType == INotifyPropertyChanged_t) + .FirstOrDefault(); + var basePropChangedAdd = basePropChangedEvent?.GetAddMethod(); + var basePropChangedRemove = basePropChangedEvent?.GetRemoveMethod(); + + var PropertyChanged_backing = typeBuilder.DefineField("PropertyChanged", PropertyChangedEventHandler_t, FieldAttributes.Private); + + var add_PropertyChanged = typeBuilder.DefineMethod("PropertyChanged", + MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual, + null, new[] { PropertyChangedEventHandler_t }); + typeBuilder.DefineMethodOverride(add_PropertyChanged, INotifyPropertyChanged_PropertyChanged.GetAddMethod()); + if (basePropChangedAdd != null) + typeBuilder.DefineMethodOverride(add_PropertyChanged, basePropChangedAdd); - var loopLabel = il.DefineLabel(); - var delTemp = il.DeclareLocal(PropertyChangedEventHandler_t); + { + var il = add_PropertyChanged.GetILGenerator(); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, PropertyChanged_backing); + var loopLabel = il.DefineLabel(); + var delTemp = il.DeclareLocal(PropertyChangedEventHandler_t); - il.MarkLabel(loopLabel); - il.Emit(OpCodes.Stloc, delTemp); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldfld, PropertyChanged_backing); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldflda, PropertyChanged_backing); + il.MarkLabel(loopLabel); + il.Emit(OpCodes.Stloc, delTemp); - il.Emit(OpCodes.Ldloc, delTemp); - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Call, Delegate_Combine); - il.Emit(OpCodes.Castclass, PropertyChangedEventHandler_t); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldflda, PropertyChanged_backing); - il.Emit(OpCodes.Ldloc, delTemp); - il.Emit(OpCodes.Call, CompareExchange); + il.Emit(OpCodes.Ldloc, delTemp); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Call, Delegate_Combine); + il.Emit(OpCodes.Castclass, PropertyChangedEventHandler_t); - il.Emit(OpCodes.Dup); - il.Emit(OpCodes.Ldloc, delTemp); - il.Emit(OpCodes.Bne_Un_S, loopLabel); + il.Emit(OpCodes.Ldloc, delTemp); + il.Emit(OpCodes.Call, CompareExchange); - il.Emit(OpCodes.Pop); - il.Emit(OpCodes.Ret); - } + il.Emit(OpCodes.Dup); + il.Emit(OpCodes.Ldloc, delTemp); + il.Emit(OpCodes.Bne_Un_S, loopLabel); - var remove_PropertyChanged = typeBuilder.DefineMethod("PropertyChanged", - MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual, - null, new[] { PropertyChangedEventHandler_t }); - typeBuilder.DefineMethodOverride(remove_PropertyChanged, INotifyPropertyChanged_PropertyChanged.GetRemoveMethod()); - if (basePropChangedRemove != null) - typeBuilder.DefineMethodOverride(remove_PropertyChanged, basePropChangedRemove); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ret); + } - { - var il = remove_PropertyChanged.GetILGenerator(); + var remove_PropertyChanged = typeBuilder.DefineMethod("PropertyChanged", + MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.Virtual, + null, new[] { PropertyChangedEventHandler_t }); + typeBuilder.DefineMethodOverride(remove_PropertyChanged, INotifyPropertyChanged_PropertyChanged.GetRemoveMethod()); + if (basePropChangedRemove != null) + typeBuilder.DefineMethodOverride(remove_PropertyChanged, basePropChangedRemove); - var loopLabel = il.DefineLabel(); - var delTemp = il.DeclareLocal(PropertyChangedEventHandler_t); + { + var il = remove_PropertyChanged.GetILGenerator(); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, PropertyChanged_backing); + var loopLabel = il.DefineLabel(); + var delTemp = il.DeclareLocal(PropertyChangedEventHandler_t); - il.MarkLabel(loopLabel); - il.Emit(OpCodes.Stloc, delTemp); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldfld, PropertyChanged_backing); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldflda, PropertyChanged_backing); + il.MarkLabel(loopLabel); + il.Emit(OpCodes.Stloc, delTemp); - il.Emit(OpCodes.Ldloc, delTemp); - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Call, Delegate_Remove); - il.Emit(OpCodes.Castclass, PropertyChangedEventHandler_t); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldflda, PropertyChanged_backing); - il.Emit(OpCodes.Ldloc, delTemp); - il.Emit(OpCodes.Call, CompareExchange); + il.Emit(OpCodes.Ldloc, delTemp); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Call, Delegate_Remove); + il.Emit(OpCodes.Castclass, PropertyChangedEventHandler_t); - il.Emit(OpCodes.Dup); - il.Emit(OpCodes.Ldloc, delTemp); - il.Emit(OpCodes.Bne_Un_S, loopLabel); + il.Emit(OpCodes.Ldloc, delTemp); + il.Emit(OpCodes.Call, CompareExchange); - il.Emit(OpCodes.Pop); - il.Emit(OpCodes.Ret); - } + il.Emit(OpCodes.Dup); + il.Emit(OpCodes.Ldloc, delTemp); + il.Emit(OpCodes.Bne_Un_S, loopLabel); - var PropertyChanged_event = typeBuilder.DefineEvent(nameof(INotifyPropertyChanged.PropertyChanged), EventAttributes.None, PropertyChangedEventHandler_t); - PropertyChanged_event.SetAddOnMethod(add_PropertyChanged); - PropertyChanged_event.SetRemoveOnMethod(remove_PropertyChanged); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ret); + } - notifyChanged = typeBuilder.DefineMethod("<>NotifyChanged", - MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final, null, new[] { typeof(string) }); + var PropertyChanged_event = typeBuilder.DefineEvent(nameof(INotifyPropertyChanged.PropertyChanged), EventAttributes.None, PropertyChangedEventHandler_t); + PropertyChanged_event.SetAddOnMethod(add_PropertyChanged); + PropertyChanged_event.SetRemoveOnMethod(remove_PropertyChanged); - { - var il = notifyChanged.GetILGenerator(); + notifyChanged = typeBuilder.DefineMethod("<>NotifyChanged", + MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Final, null, new[] { typeof(string) }); - var invokeNonNull = il.DefineLabel(); + { + var il = notifyChanged.GetILGenerator(); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, PropertyChanged_backing); - il.Emit(OpCodes.Dup); - il.Emit(OpCodes.Brtrue, invokeNonNull); - il.Emit(OpCodes.Pop); - il.Emit(OpCodes.Ret); + var invokeNonNull = il.DefineLabel(); - il.MarkLabel(invokeNonNull); - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldarg_1); - il.Emit(OpCodes.Newobj, PropertyChangedEventArgs_ctor); - il.Emit(OpCodes.Call, PropertyChangedEventHander_Invoke); - il.Emit(OpCodes.Ret); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldfld, PropertyChanged_backing); + il.Emit(OpCodes.Dup); + il.Emit(OpCodes.Brtrue, invokeNonNull); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ret); + + il.MarkLabel(invokeNonNull); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Newobj, PropertyChangedEventArgs_ctor); + il.Emit(OpCodes.Call, PropertyChangedEventHander_Invoke); + il.Emit(OpCodes.Ret); + } } } #endregion