Silverlight中动态数据验证和动态自动计算的Reflection反射实现
2011-06-25 18:46
627 查看
Silverlight中动态数据验证和动态自动计算的Reflection反射实现
上周在博客园发了个首页随笔,因为被误认为是广告而被移出首页,这次发首页,特地备足了技术材料,结合FreeForm实际的开发情况,从技术上分析在Silverlight中实现动态数据验证和自动计算的方法。我们知道在.Net 4.0标准类库中,反射的类很全,非常好用,但在Silverlight类库中涉及反射的命名空间虽然也有System.Reflection 和System.Reflection.Emit ,但类和方法大大的缩减了。以前我们在WinForm或者ASP.Net中实现动态验证和动态计算非常容易,可以通过类似如下代码实现:View Code
class Example { public static void Demo(System.Windows.Controls.TextBlock outputBlock) { AssemblyName aName = new AssemblyName("DynamicAssemblyExample"); AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly( aName, AssemblyBuilderAccess.Run); // Create the module. ModuleBuilder mb = ab.DefineDynamicModule(aName.Name); TypeBuilder tb = mb.DefineType( "MyDynamicType", TypeAttributes.Public); // Add a private field of type int (Int32). FieldBuilder fbNumber = tb.DefineField( "m_number", typeof(int), FieldAttributes.Private); // Define a constructor that takes an integer argument and // stores it in the private field. Type[] parameterTypes = { typeof(int) }; ConstructorBuilder ctor1 = tb.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, parameterTypes); ILGenerator ctor1IL = ctor1.GetILGenerator(); // For a constructor, argument zero is a reference to the new // instance. Push it on the stack before calling the base // class constructor. Specify the default constructor of the // base class (System.Object) by passing an empty array of // types (Type.EmptyTypes) to GetConstructor. ctor1IL.Emit(OpCodes.Ldarg_0); ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); // Push the instance on the stack before pushing the argument // that is to be assigned to the private field m_number. ctor1IL.Emit(OpCodes.Ldarg_0); ctor1IL.Emit(OpCodes.Ldarg_1); ctor1IL.Emit(OpCodes.Stfld, fbNumber); ctor1IL.Emit(OpCodes.Ret); // Define a default constructor that supplies a default value // for the private field. For parameter types, pass the empty // array of types or pass null. ConstructorBuilder ctor0 = tb.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); ILGenerator ctor0IL = ctor0.GetILGenerator(); // For a constructor, argument zero is a reference to the new // instance. Push it on the stack before pushing the default // value on the stack, then call constructor ctor1. ctor0IL.Emit(OpCodes.Ldarg_0); ctor0IL.Emit(OpCodes.Ldc_I4_S, 42); ctor0IL.Emit(OpCodes.Call, ctor1); ctor0IL.Emit(OpCodes.Ret); // Define a property named Number that gets and sets the private // field. // // The last argument of DefineProperty is null, because the // property has no parameters. (If you don't specify null, you must // specify an array of Type objects. For a parameterless property, // use the built-in array with no elements: Type.EmptyTypes) PropertyBuilder pbNumber = tb.DefineProperty( "Number", PropertyAttributes.HasDefault, typeof(int), null); // The property "set" and property "get" methods require a special // set of attributes. MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; // Define the "get" accessor method for Number. The method returns // an integer and has no arguments. (Note that null could be // used instead of Types.EmptyTypes) MethodBuilder mbNumberGetAccessor = tb.DefineMethod( "get_Number", getSetAttr, typeof(int), Type.EmptyTypes); ILGenerator numberGetIL = mbNumberGetAccessor.GetILGenerator(); // For an instance property, argument zero is the instance. Load the // instance, then load the private field and return, leaving the // field value on the stack. numberGetIL.Emit(OpCodes.Ldarg_0); numberGetIL.Emit(OpCodes.Ldfld, fbNumber); numberGetIL.Emit(OpCodes.Ret); // Define the "set" accessor method for Number, which has no return // type and takes one argument of type int (Int32). MethodBuilder mbNumberSetAccessor = tb.DefineMethod( "set_Number", getSetAttr, null, new Type[] { typeof(int) }); ILGenerator numberSetIL = mbNumberSetAccessor.GetILGenerator(); // Load the instance and then the numeric argument, then store the // argument in the field. numberSetIL.Emit(OpCodes.Ldarg_0); numberSetIL.Emit(OpCodes.Ldarg_1); numberSetIL.Emit(OpCodes.Stfld, fbNumber); numberSetIL.Emit(OpCodes.Ret); // Last, map the "get" and "set" accessor methods to the // PropertyBuilder. The property is now complete. pbNumber.SetGetMethod(mbNumberGetAccessor); pbNumber.SetSetMethod(mbNumberSetAccessor); // Define a method that accepts an integer argument and returns // the product of that integer and the private field m_number. This // time, the array of parameter types is created on the fly. MethodBuilder meth = tb.DefineMethod( "MyMethod", MethodAttributes.Public, typeof(int), new Type[] { typeof(int) }); ILGenerator methIL = meth.GetILGenerator(); // To retrieve the private instance field, load the instance it // belongs to (argument zero). After loading the field, load the // argument one and then multiply. Return from the method with // the return value (the product of the two numbers) on the // execution stack. methIL.Emit(OpCodes.Ldarg_0); methIL.Emit(OpCodes.Ldfld, fbNumber); methIL.Emit(OpCodes.Ldarg_1); methIL.Emit(OpCodes.Mul); methIL.Emit(OpCodes.Ret); // Finish the type. Type t = tb.CreateType(); // The code can be executed immediately. Start by getting reflection // objects for the method and the property. MethodInfo mi = t.GetMethod("MyMethod"); PropertyInfo pi = t.GetProperty("Number"); // Create an instance of MyDynamicType using the default // constructor. object o1 = Activator.CreateInstance(t); // Display the value of the property, then change it to 127 and // display it again. Use null to indicate that the property // has no index. outputBlock.Text += String.Format("o1.Number: {0}\n", pi.GetValue(o1, null)); pi.SetValue(o1, 127, null); outputBlock.Text += String.Format("o1.Number: {0}\n", pi.GetValue(o1, null)); // Call MyMethod, passing 22, and display the return value, 22 // times 127. Arguments must be passed as an array, even when // there is only one. object[] arguments = { 22 }; outputBlock.Text += String.Format("o1.MyMethod(22): {0}\n", mi.Invoke(o1, arguments)); // Create an instance of MyDynamicType using the constructor // that specifies m_Number. The constructor is identified by // matching the types in the argument array. In this case, // the argument array is created on the fly. Display the // property value. object o2 = Activator.CreateInstance(t, new object[] { 5280 }); outputBlock.Text += String.Format("o2.Number: {0}\n", pi.GetValue(o2, null)); } }
好了,原理清晰了,一起看看在Siverlight上实现的例子吧(一定要看最后一节的“动态自定义验证
”),感谢大家。
在线演示(ver2011):
http://crmwin.com/FreeForm2011TestPage.html
相关文章推荐
- [原创]Silverlight中动态数据验证和动态自动计算的Reflection反射实现
- 智能表单设计器Web Free Form Designer:FreeForm动态数据验证和动态自动计算
- 智能表单设计器Web Free Form Designer:FreeForm动态数据验证和动态自动计算
- 以申购单为实例,讲解Jquery动态删减行,新增行添加鼠标事件,子窗口与父窗口传值,自动计算金额,及输入值的验证,前台数据批量提交到后台action
- 利用反射实现ASP.NET控件和数据实体之间的双向绑定,并且在客户端自动验证输入的内容是否合法
- MVC中 数据底层联合JQUERY实现动态的安全的验证机制
- javascript/HTML实现多个text控件自动/动态计算总数
- WPF and Silverlight 学习笔记(二十二):使用代码实现绑定、绑定数据的验证
- 用反射实现表单和Model之间互相传自动递数据
- 实现Excel行插入行删除特殊处理,单元格合并及动态条件单元格公式自动计算功能的VBA 宏示例
- 大数据IMF传奇行动绝密课程第97课:使用SparkStreaming+SparkSQL实现在线动态计算出特定时间窗口
- 基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- easyui复选框树动态加载后台数据,实现自动选中数据库中数据。后台语言是.NET
- C#通过反射来动态创建类对象并调用相关泛型函数(Excel数据自动导入到SQL Server数据库)
- 【VS开发】【图像处理】基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 发布Silverlight项目自动生成模板,自动生成Silverlight调用RIA Service实现数据增删查改
- JavaBean 反射机制实现自动配置数据
- 基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 利用Java Reflection(反射)原理,在hibernate里面实现对单表、视图的动态组合查询