| namespace EmitCreateDynamicProxy | namespace EmitCreateDynamicProxy | ||||
| { | { | ||||
| class DDD : INotifyPropertyChanged | |||||
| class DDD// : INotifyPropertyChanged | |||||
| { | { | ||||
| public event PropertyChangedEventHandler PropertyChanged; | |||||
| //public event PropertyChangedEventHandler PropertyChanged; | |||||
| public string Name { get => _Name; set { _Name = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("uuu")); } } | |||||
| public string Name { get => _Name; set { _Name = value; } } //PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name")); } } | |||||
| private string _Name = ""; | private string _Name = ""; | ||||
| } | } | ||||
| } | } |
| string proxyClassName = string.Format(ProxyClassNameFormater, typeNeedProxy.Name); | string proxyClassName = string.Format(ProxyClassNameFormater, typeNeedProxy.Name); | ||||
| //动态创建类代理 | //动态创建类代理 | ||||
| TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(proxyClassName, TypeAttributes.Public, typeNeedProxy); | TypeBuilder typeBuilderProxy = moduleBuilder.DefineType(proxyClassName, TypeAttributes.Public, typeNeedProxy); | ||||
| //定义一个变量存放属性变更名 | |||||
| FieldBuilder fbModifiedPropertyNames = typeBuilderProxy.DefineField(ModifiedPropertyNamesFieldName, modifiedPropertyNamesType, FieldAttributes.Public); | |||||
| /* | |||||
| * 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码 | |||||
| ModifiedPropertyNames = new List<string>(); | |||||
| */ | |||||
| ConstructorBuilder constructorBuilder = typeBuilderProxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null); | |||||
| ILGenerator ilgCtor = constructorBuilder.GetILGenerator(); | |||||
| ilgCtor.Emit(OpCodes.Ldarg_0);//加载当前类 | |||||
| ilgCtor.Emit(OpCodes.Call, typeNeedProxy.GetConstructor(Type.EmptyTypes)); | |||||
| ilgCtor.Emit(OpCodes.Nop); | |||||
| ilgCtor.Emit(OpCodes.Ret);//返回 | |||||
| //定义接口 | //定义接口 | ||||
| var pt = typeof(PropertyChangedEventHandler); | var pt = typeof(PropertyChangedEventHandler); | ||||
| typeBuilderProxy.AddInterfaceImplementation(typeof(INotifyPropertyChanged)); | typeBuilderProxy.AddInterfaceImplementation(typeof(INotifyPropertyChanged)); | ||||
| var eil = typeBuilderProxy.DefineEvent("PropertyChanged", EventAttributes.None, typeof(PropertyChangedEventHandler)); | |||||
| var eil = typeBuilderProxy.DefineEvent("PropertyChanged", EventAttributes.SpecialName, typeof(PropertyChangedEventHandler)); | |||||
| //add field | //add field | ||||
| var eb = typeBuilderProxy.DefineField("PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Private); | |||||
| var eb = typeBuilderProxy.DefineField("_PropertyChanged", typeof(PropertyChangedEventHandler), FieldAttributes.Private); | |||||
| var compareExchange = GetGenericMethod(typeof(Interlocked), "CompareExchange");// finds the correct method to call. | var compareExchange = GetGenericMethod(typeof(Interlocked), "CompareExchange");// finds the correct method to call. | ||||
| // thanks to @marc, create the specific method with the correct type | // thanks to @marc, create the specific method with the correct type | ||||
| | MethodAttributes.NewSlot | MethodAttributes.SpecialName | MethodAttributes.Virtual | MethodAttributes.Final; | | MethodAttributes.NewSlot | MethodAttributes.SpecialName | MethodAttributes.Virtual | MethodAttributes.Final; | ||||
| var mb = typeBuilderProxy.DefineMethod("add_PropertyChanged", mas, typeof(void), new Type[] { pt }); | var mb = typeBuilderProxy.DefineMethod("add_PropertyChanged", mas, typeof(void), new Type[] { pt }); | ||||
| mb.DefineParameter(0, ParameterAttributes.Retval, null); | mb.DefineParameter(0, ParameterAttributes.Retval, null); | ||||
| mb.DefineParameter(1, ParameterAttributes.In, "value"); | |||||
| mb.DefineParameter(1, ParameterAttributes.None, "value"); | |||||
| var il = mb.GetILGenerator(); | var il = mb.GetILGenerator(); | ||||
| il.DeclareLocal(pt); | il.DeclareLocal(pt); | ||||
| il.DeclareLocal(pt); | il.DeclareLocal(pt); | ||||
| il.Emit(OpCodes.Bne_Un_S, lable); | il.Emit(OpCodes.Bne_Un_S, lable); | ||||
| il.Emit(OpCodes.Ret); | il.Emit(OpCodes.Ret); | ||||
| eil.SetAddOnMethod(mb); | |||||
| //remove event | //remove event | ||||
| mb = typeBuilderProxy.DefineMethod("remove_PropertyChanged", mas, typeof(void), new Type[] { pt }); | mb = typeBuilderProxy.DefineMethod("remove_PropertyChanged", mas, typeof(void), new Type[] { pt }); | ||||
| mb.DefineParameter(0, ParameterAttributes.Retval, null); | mb.DefineParameter(0, ParameterAttributes.Retval, null); | ||||
| mb.DefineParameter(1, ParameterAttributes.In, "value"); | |||||
| mb.DefineParameter(1, ParameterAttributes.None, "value"); | |||||
| il = mb.GetILGenerator(); | il = mb.GetILGenerator(); | ||||
| il.DeclareLocal(pt); | il.DeclareLocal(pt); | ||||
| il.Emit(OpCodes.Bne_Un_S, lable); | il.Emit(OpCodes.Bne_Un_S, lable); | ||||
| il.Emit(OpCodes.Ret); | il.Emit(OpCodes.Ret); | ||||
| /* | |||||
| * 构造函数 实例化 ModifiedPropertyNames,生成类似于下面的代码 | |||||
| ModifiedPropertyNames = new List<string>(); | |||||
| */ | |||||
| ConstructorBuilder constructorBuilder = typeBuilderProxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null); | |||||
| ILGenerator ilgCtor = constructorBuilder.GetILGenerator(); | |||||
| ilgCtor.Emit(OpCodes.Ldarg_0);//加载当前类 | |||||
| ilgCtor.Emit(OpCodes.Newobj, modifiedPropertyNamesType.GetConstructor(new Type[0]));//实例化对象入栈 | |||||
| ilgCtor.Emit(OpCodes.Stfld, fbModifiedPropertyNames);//设置fbModifiedPropertyNames值,为刚入栈的实例化对象 | |||||
| ilgCtor.Emit(OpCodes.Ret);//返回 | |||||
| eil.SetRemoveOnMethod(mb); | |||||
| //获取被代理对象的所有属性,循环属性进行重写 | //获取被代理对象的所有属性,循环属性进行重写 | ||||
| PropertyInfo[] properties = typeNeedProxy.GetProperties(); | PropertyInfo[] properties = typeNeedProxy.GetProperties(); | ||||
| string propertyName = propertyInfo.Name; | string propertyName = propertyInfo.Name; | ||||
| Type typePepropertyInfo = propertyInfo.PropertyType; | Type typePepropertyInfo = propertyInfo.PropertyType; | ||||
| //动态创建字段和属性 | //动态创建字段和属性 | ||||
| FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_" + propertyName, typePepropertyInfo, FieldAttributes.Private); | |||||
| PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.SpecialName, typePepropertyInfo, null); | |||||
| PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty(propertyName, PropertyAttributes.None, typePepropertyInfo, Type.EmptyTypes); | |||||
| //重写属性的Get Set方法 | //重写属性的Get Set方法 | ||||
| //Method 搞的一直调用不成功,应该是写的时候没有加上CheckAccessOnOverride | |||||
| var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, GetSetMethodAttributes, typePepropertyInfo, Type.EmptyTypes); | var methodGet = typeBuilderProxy.DefineMethod("get_" + propertyName, GetSetMethodAttributes, typePepropertyInfo, Type.EmptyTypes); | ||||
| var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, GetSetMethodAttributes, null, new Type[] { typePepropertyInfo }); | |||||
| var methodSet = typeBuilderProxy.DefineMethod("set_" + propertyName, GetSetMethodAttributes, typeof(void), new Type[] { typePepropertyInfo }); | |||||
| //il of get method | //il of get method | ||||
| var ilGetMethod = methodGet.GetILGenerator(); | var ilGetMethod = methodGet.GetILGenerator(); | ||||
| ilGetMethod.Emit(OpCodes.Nop); | |||||
| ilGetMethod.Emit(OpCodes.Ldstr, "Before Do"); | |||||
| ilGetMethod.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); | |||||
| ilGetMethod.Emit(OpCodes.Ldarg_0); | ilGetMethod.Emit(OpCodes.Ldarg_0); | ||||
| ilGetMethod.Emit(OpCodes.Ldfld, fieldBuilder); | |||||
| ilGetMethod.Emit(OpCodes.Call, typeNeedProxy.GetMethod("get_" + propertyName)); | |||||
| ilGetMethod.Emit(OpCodes.Ret); | ilGetMethod.Emit(OpCodes.Ret); | ||||
| //il of set method | //il of set method | ||||
| methodSet.DefineParameter(0, ParameterAttributes.Retval, null); | |||||
| methodSet.DefineParameter(1, ParameterAttributes.None, "value"); | |||||
| ILGenerator ilSetMethod = methodSet.GetILGenerator(); | ILGenerator ilSetMethod = methodSet.GetILGenerator(); | ||||
| var nullLabel = ilSetMethod.DefineLabel(); | var nullLabel = ilSetMethod.DefineLabel(); | ||||
| ilSetMethod.Emit(OpCodes.Nop); | |||||
| ilSetMethod.Emit(OpCodes.Ldarg_0); | ilSetMethod.Emit(OpCodes.Ldarg_0); | ||||
| ilSetMethod.Emit(OpCodes.Ldarg_1); | ilSetMethod.Emit(OpCodes.Ldarg_1); | ||||
| ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder); | |||||
| ilSetMethod.Emit(OpCodes.Call, typeNeedProxy.GetMethod("set_" + propertyName)); | |||||
| ilSetMethod.Emit(OpCodes.Nop); | |||||
| ilSetMethod.Emit(OpCodes.Ldstr, "Before Do"); | |||||
| ilSetMethod.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); | |||||
| ilSetMethod.Emit(OpCodes.Nop); | |||||
| ilSetMethod.Emit(OpCodes.Ldarg_0); | ilSetMethod.Emit(OpCodes.Ldarg_0); | ||||
| ilSetMethod.Emit(OpCodes.Ldfld, fbModifiedPropertyNames); | |||||
| ilSetMethod.Emit(OpCodes.Ldfld, eb); | |||||
| ilSetMethod.Emit(OpCodes.Dup); | ilSetMethod.Emit(OpCodes.Dup); | ||||
| ilSetMethod.Emit(OpCodes.Brtrue_S, nullLabel); | ilSetMethod.Emit(OpCodes.Brtrue_S, nullLabel); | ||||
| ilSetMethod.Emit(OpCodes.Pop); | ilSetMethod.Emit(OpCodes.Pop); | ||||
| ilSetMethod.MarkLabel(nullLabel); | ilSetMethod.MarkLabel(nullLabel); | ||||
| ilSetMethod.Emit(OpCodes.Ldarg_0); | ilSetMethod.Emit(OpCodes.Ldarg_0); | ||||
| ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name); | ilSetMethod.Emit(OpCodes.Ldstr, propertyInfo.Name); | ||||
| ilSetMethod.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs)); | |||||
| ilSetMethod.Emit(OpCodes.Newobj, typeof(PropertyChangedEventArgs).GetConstructor(new Type[] { typeof(string) })); | |||||
| ilSetMethod.Emit(OpCodes.Callvirt, pt.GetMethod("Invoke", new Type[] { typeof(object), typeof(PropertyChangedEventArgs) })); | ilSetMethod.Emit(OpCodes.Callvirt, pt.GetMethod("Invoke", new Type[] { typeof(object), typeof(PropertyChangedEventArgs) })); | ||||
| ilSetMethod.Emit(OpCodes.Nop); | ilSetMethod.Emit(OpCodes.Nop); | ||||
| il.MarkLabel(retLabel); | |||||
| ilSetMethod.Emit(OpCodes.Ldstr, "After Do"); | |||||
| ilSetMethod.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); | |||||
| ilSetMethod.Emit(OpCodes.Nop); | |||||
| ilSetMethod.MarkLabel(retLabel); | |||||
| ilSetMethod.Emit(OpCodes.Ret); | ilSetMethod.Emit(OpCodes.Ret); | ||||
| //ilSetMethod.Emit(OpCodes.Nop); | |||||
| //ilSetMethod.Emit(OpCodes.Ldarg_0); | |||||
| //ilSetMethod.Emit(OpCodes.Ldarg_1); | |||||
| //ilSetMethod.Emit(OpCodes.Stfld, fieldBuilder); | |||||
| //ilSetMethod.Emit(OpCodes.Ret); | |||||
| //设置属性的Get Set方法 | //设置属性的Get Set方法 | ||||
| propertyBuilder.SetGetMethod(methodGet); | propertyBuilder.SetGetMethod(methodGet); | ||||
| propertyBuilder.SetSetMethod(methodSet); | propertyBuilder.SetSetMethod(methodSet); | ||||
| return (T)instance; | return (T)instance; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// 获取属性的变更名称, | |||||
| /// 此处只检测调用了Set方法的属性,不会检测值是否真的有变 | |||||
| /// </summary> | |||||
| /// <param name="obj"></param> | |||||
| /// <returns></returns> | |||||
| public static HashSet<string> GetModifiedProperties(object obj) | |||||
| { | |||||
| FieldInfo fieldInfo = obj.GetType().GetField(ModifiedPropertyNamesFieldName); | |||||
| if (fieldInfo == null) return null; | |||||
| object value = fieldInfo.GetValue(obj); | |||||
| return value as HashSet<string>; | |||||
| } | |||||
| private static MethodInfo GetGenericMethod(Type type, string methodName) | private static MethodInfo GetGenericMethod(Type type, string methodName) | ||||
| { | { | ||||
| var q = from m in type.GetMethods() | var q = from m in type.GetMethods() |
| <ItemGroup> | <ItemGroup> | ||||
| <Compile Include="DDD.cs" /> | <Compile Include="DDD.cs" /> | ||||
| <Compile Include="DynamicProxyGenerator.cs" /> | <Compile Include="DynamicProxyGenerator.cs" /> | ||||
| <Compile Include="M.cs" /> | |||||
| <Compile Include="Model.cs" /> | <Compile Include="Model.cs" /> | ||||
| <Compile Include="Program.cs" /> | <Compile Include="Program.cs" /> | ||||
| <Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> |
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.ComponentModel; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| namespace EmitCreateDynamicProxy | |||||
| { | |||||
| class M : Model, INotifyPropertyChanged | |||||
| { | |||||
| public override string Name | |||||
| { | |||||
| get => base.Name; set | |||||
| { | |||||
| base.Name = value; | |||||
| Console.WriteLine("Before"); | |||||
| PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name")); | |||||
| Console.WriteLine("After"); | |||||
| } | |||||
| } | |||||
| public event PropertyChangedEventHandler PropertyChanged; | |||||
| } | |||||
| } |
| { | { | ||||
| public class Model | public class Model | ||||
| { | { | ||||
| public virtual string LoginName { get; set; } | |||||
| public virtual string Password { get; set; } | |||||
| public virtual string Name { get; set; } | |||||
| } | } | ||||
| } | } |
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.ComponentModel; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Reflection; | using System.Reflection; | ||||
| using System.Reflection.Emit; | using System.Reflection.Emit; | ||||
| //Console.ReadLine(); | //Console.ReadLine(); | ||||
| Model m = DynamicProxyGenerator.CreateDynamicProxy<Model>(true); | Model m = DynamicProxyGenerator.CreateDynamicProxy<Model>(true); | ||||
| m.LoginName = "ddd"; | |||||
| HashSet<string> modifiedPropertyNames = DynamicProxyGenerator.GetModifiedProperties(m) as HashSet<string>; | |||||
| var pc = m as INotifyPropertyChanged; | |||||
| pc.PropertyChanged += Pc_PropertyChanged; | |||||
| m.Name = "ddd"; | |||||
| var d = new DDD(); | |||||
| //d.PropertyChanged += Pc_PropertyChanged; | |||||
| d.Name = "nnn"; | |||||
| //var x = new M(); | |||||
| //x.Name = "000"; | |||||
| Console.WriteLine("........"); | |||||
| Console.ReadKey(); | |||||
| } | |||||
| private static void Pc_PropertyChanged(object sender, PropertyChangedEventArgs e) | |||||
| { | |||||
| Console.WriteLine($"PropertyChanged {e.PropertyName}"); | |||||
| } | } | ||||
| } | } | ||||
| | | ||||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||||
| # Visual Studio 2010 | |||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
| # Visual Studio 15 | |||||
| VisualStudioVersion = 15.0.28307.329 | |||||
| MinimumVisualStudioVersion = 10.0.40219.1 | |||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitIntroduction", "EmitIntroduction\EmitIntroduction.csproj", "{38396364-FAFD-4D67-B265-32B108A797C0}" | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitIntroduction", "EmitIntroduction\EmitIntroduction.csproj", "{38396364-FAFD-4D67-B265-32B108A797C0}" | ||||
| EndProject | EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitCreateMembers", "EmitCreateMembers\EmitCreateMembers.csproj", "{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}" | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitCreateMembers", "EmitCreateMembers\EmitCreateMembers.csproj", "{C4DFB7F2-8C56-4036-B4FF-E56B456B3943}" | ||||
| EndProject | EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitCreateDynamicProxy", "EmitCreateDynamicProxy\EmitCreateDynamicProxy.csproj", "{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}" | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmitCreateDynamicProxy", "EmitCreateDynamicProxy\EmitCreateDynamicProxy.csproj", "{BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}" | ||||
| EndProject | EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{06CB2095-2D8D-4B3D-96D9-451BCFB095F4}" | |||||
| EndProject | |||||
| Global | Global | ||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| Debug|Any CPU = Debug|Any CPU | |||||
| Debug|x86 = Debug|x86 | Debug|x86 = Debug|x86 | ||||
| Release|Any CPU = Release|Any CPU | |||||
| Release|x86 = Release|x86 | Release|x86 = Release|x86 | ||||
| EndGlobalSection | EndGlobalSection | ||||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| {38396364-FAFD-4D67-B265-32B108A797C0}.Debug|Any CPU.ActiveCfg = Debug|x86 | |||||
| {38396364-FAFD-4D67-B265-32B108A797C0}.Debug|x86.ActiveCfg = Debug|x86 | {38396364-FAFD-4D67-B265-32B108A797C0}.Debug|x86.ActiveCfg = Debug|x86 | ||||
| {38396364-FAFD-4D67-B265-32B108A797C0}.Debug|x86.Build.0 = Debug|x86 | {38396364-FAFD-4D67-B265-32B108A797C0}.Debug|x86.Build.0 = Debug|x86 | ||||
| {38396364-FAFD-4D67-B265-32B108A797C0}.Release|Any CPU.ActiveCfg = Release|x86 | |||||
| {38396364-FAFD-4D67-B265-32B108A797C0}.Release|x86.ActiveCfg = Release|x86 | {38396364-FAFD-4D67-B265-32B108A797C0}.Release|x86.ActiveCfg = Release|x86 | ||||
| {38396364-FAFD-4D67-B265-32B108A797C0}.Release|x86.Build.0 = Release|x86 | {38396364-FAFD-4D67-B265-32B108A797C0}.Release|x86.Build.0 = Release|x86 | ||||
| {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Debug|Any CPU.ActiveCfg = Debug|x86 | |||||
| {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Debug|x86.ActiveCfg = Debug|x86 | {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Debug|x86.ActiveCfg = Debug|x86 | ||||
| {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Debug|x86.Build.0 = Debug|x86 | {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Debug|x86.Build.0 = Debug|x86 | ||||
| {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Release|Any CPU.ActiveCfg = Release|x86 | |||||
| {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Release|x86.ActiveCfg = Release|x86 | {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Release|x86.ActiveCfg = Release|x86 | ||||
| {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Release|x86.Build.0 = Release|x86 | {C4DFB7F2-8C56-4036-B4FF-E56B456B3943}.Release|x86.Build.0 = Release|x86 | ||||
| {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Debug|Any CPU.ActiveCfg = Debug|x86 | |||||
| {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Debug|x86.ActiveCfg = Debug|x86 | {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Debug|x86.ActiveCfg = Debug|x86 | ||||
| {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Debug|x86.Build.0 = Debug|x86 | {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Debug|x86.Build.0 = Debug|x86 | ||||
| {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Release|Any CPU.ActiveCfg = Release|x86 | |||||
| {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Release|x86.ActiveCfg = Release|x86 | {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Release|x86.ActiveCfg = Release|x86 | ||||
| {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Release|x86.Build.0 = Release|x86 | {BDA6268A-ADF2-4DA3-8053-81CA4AD007B0}.Release|x86.Build.0 = Release|x86 | ||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Debug|x86.ActiveCfg = Debug|Any CPU | |||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Debug|x86.Build.0 = Debug|Any CPU | |||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Release|x86.ActiveCfg = Release|Any CPU | |||||
| {06CB2095-2D8D-4B3D-96D9-451BCFB095F4}.Release|x86.Build.0 = Release|Any CPU | |||||
| EndGlobalSection | EndGlobalSection | ||||
| GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
| HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||
| EndGlobalSection | EndGlobalSection | ||||
| GlobalSection(ExtensibilityGlobals) = postSolution | |||||
| SolutionGuid = {B43E4E3D-CF60-498A-9F7D-51F46275BBD6} | |||||
| EndGlobalSection | |||||
| EndGlobal | EndGlobal |
| <?xml version="1.0" encoding="utf-8" ?> | |||||
| <configuration> | |||||
| <startup> | |||||
| <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> | |||||
| </startup> | |||||
| </configuration> |
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace Test | |||||
| { | |||||
| class Program | |||||
| { | |||||
| static void Main(string[] args) | |||||
| { | |||||
| ModelProxy m = new ModelProxy(); | |||||
| m.PropertyChanged += M_PropertyChanged; | |||||
| m.Name = "333"; | |||||
| Console.ReadLine(); | |||||
| } | |||||
| private static void M_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) | |||||
| { | |||||
| Console.WriteLine("Run Run Run"); | |||||
| } | |||||
| } | |||||
| } |
| using System.Reflection; | |||||
| using System.Runtime.CompilerServices; | |||||
| using System.Runtime.InteropServices; | |||||
| // 有关程序集的一般信息由以下 | |||||
| // 控制。更改这些特性值可修改 | |||||
| // 与程序集关联的信息。 | |||||
| [assembly: AssemblyTitle("Test")] | |||||
| [assembly: AssemblyDescription("")] | |||||
| [assembly: AssemblyConfiguration("")] | |||||
| [assembly: AssemblyCompany("")] | |||||
| [assembly: AssemblyProduct("Test")] | |||||
| [assembly: AssemblyCopyright("Copyright © 2019")] | |||||
| [assembly: AssemblyTrademark("")] | |||||
| [assembly: AssemblyCulture("")] | |||||
| // 将 ComVisible 设置为 false 会使此程序集中的类型 | |||||
| //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 | |||||
| //请将此类型的 ComVisible 特性设置为 true。 | |||||
| [assembly: ComVisible(false)] | |||||
| // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID | |||||
| [assembly: Guid("06cb2095-2d8d-4b3d-96d9-451bcfb095f4")] | |||||
| // 程序集的版本信息由下列四个值组成: | |||||
| // | |||||
| // 主版本 | |||||
| // 次版本 | |||||
| // 生成号 | |||||
| // 修订号 | |||||
| // | |||||
| // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 | |||||
| // 方法是按如下所示使用“*”: : | |||||
| // [assembly: AssemblyVersion("1.0.*")] | |||||
| [assembly: AssemblyVersion("1.0.0.0")] | |||||
| [assembly: AssemblyFileVersion("1.0.0.0")] |
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
| <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||||
| <PropertyGroup> | |||||
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||||
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||||
| <ProjectGuid>{06CB2095-2D8D-4B3D-96D9-451BCFB095F4}</ProjectGuid> | |||||
| <OutputType>Exe</OutputType> | |||||
| <RootNamespace>Test</RootNamespace> | |||||
| <AssemblyName>Test</AssemblyName> | |||||
| <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> | |||||
| <FileAlignment>512</FileAlignment> | |||||
| <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | |||||
| <Deterministic>true</Deterministic> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||||
| <PlatformTarget>AnyCPU</PlatformTarget> | |||||
| <DebugSymbols>true</DebugSymbols> | |||||
| <DebugType>full</DebugType> | |||||
| <Optimize>false</Optimize> | |||||
| <OutputPath>bin\Debug\</OutputPath> | |||||
| <DefineConstants>DEBUG;TRACE</DefineConstants> | |||||
| <ErrorReport>prompt</ErrorReport> | |||||
| <WarningLevel>4</WarningLevel> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||||
| <PlatformTarget>AnyCPU</PlatformTarget> | |||||
| <DebugType>pdbonly</DebugType> | |||||
| <Optimize>true</Optimize> | |||||
| <OutputPath>bin\Release\</OutputPath> | |||||
| <DefineConstants>TRACE</DefineConstants> | |||||
| <ErrorReport>prompt</ErrorReport> | |||||
| <WarningLevel>4</WarningLevel> | |||||
| </PropertyGroup> | |||||
| <ItemGroup> | |||||
| <Reference Include="DynamicAssembly"> | |||||
| <HintPath>..\EmitCreateDynamicProxy\bin\Debug\DynamicAssembly.dll</HintPath> | |||||
| </Reference> | |||||
| <Reference Include="EmitCreateDynamicProxy"> | |||||
| <HintPath>..\EmitCreateDynamicProxy\bin\Debug\EmitCreateDynamicProxy.exe</HintPath> | |||||
| </Reference> | |||||
| <Reference Include="System" /> | |||||
| <Reference Include="System.Core" /> | |||||
| <Reference Include="System.Xml.Linq" /> | |||||
| <Reference Include="System.Data.DataSetExtensions" /> | |||||
| <Reference Include="Microsoft.CSharp" /> | |||||
| <Reference Include="System.Data" /> | |||||
| <Reference Include="System.Net.Http" /> | |||||
| <Reference Include="System.Xml" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <Compile Include="Program.cs" /> | |||||
| <Compile Include="Properties\AssemblyInfo.cs" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <None Include="App.config" /> | |||||
| </ItemGroup> | |||||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||||
| </Project> |