zoukankan      html  css  js  c++  java
  • 动态类型与PropertyGrid

    背景
      我在一个项目中遇到这样一件事。一开始用户对要编辑的数据
    没有多少要求,于是我用PropertyGrid来提供编辑界面,我的开
    发被大大简化了。但是用户使用了一段时间后提出,所有对象的
    属性个数必须可以动态增减,甚至在运行中。虽然他们再次表示
    增减的个数不会超过5个,但是这次我选择不相信他们了,我需要
    一个具有一定弹性的设计。于是每个对象会自带一个Dictionary保
    存属性。我再提供配置文件来描述每种对象的属性表。到目前为止
    一切OK。但是当我将这个对象赋给PropertyGrid时问题来了,这个
    控件竟然不允许手动增减属性,她只接受对象的public property!

    问题
      如上所述
      1、我们有一个对象,对象要编辑的属性不是它自身的property,
      而是保存在一个Dictionary里;
      2、对象属性的编辑界面PropertyGrid只接受public property;
      3、我不想自己开发编辑界面;

    分析
      根据需求我们不难看出真正困扰我的其实是第3条,而这一条是
    我自己强加的,用户对编辑界面的唯一要求就是简单,
    PropertyGrid他们认可,Label加TextBox他们也认可,在这方面他
    们其实是很可爱的。
      我现在可以放弃我自己的需求实现一个Label加TextBox的对话框
    ,也可以用DataGridView。其实只要放弃PropertyGrid我有很多选
    择。但是我喜欢PropertyGrid,他在这个项目中正合适,而且我自
    己很难实现出它的效果。
      其实说白了,我们只要把Dictionary中间的键值对变成对象的
    property就行了,所有的矛盾一下归结为:如何创建一个对象,它
    的property都来自Dictionary中间的键值对。这时我的脑海中闪出
    一个单词“Emit”。
      Emit是一个很强大的功能,但是不太好用(大概这是一个铁律:
    强大的都不好驾驭),我也就没有认真学习过。现在机会来了。
    我在这里只简单介绍一下Emit的使用,感兴趣的可以深入学习,最
    好能把学习成果发布到这里与大家分享。

    Emit简介
      Emit是一种允许代码在运行时创建并执行代码的功能,用它创建
    的代码功能有限制,但是执行效率与编译后的代码无异。提醒一下
    ,想使用Emit需要对DotNet的内存模型有一定的了解,更重要的是
    需要了解IL的知识。下面我用一个例子说明使用Emit的大致流程,
    一个HelloWorld程序;)

    (这段代码来自项目exam/exam1)

    Code



      上面的代码先创建了一个程序集“DynamicAssembly”,然后给程序集增加
    一个模块“DynamicModule”,最后在模块中创建类型“DynamicClass”。这是
    使用Emit的经典步骤。在得到类型以后真正的工作才开始。上面的代码只
    是为类型定义了一个函数“Greet”,然后用ILGenerator来为函数注入代码:
    Console.WriteLine("HelloWorld")。

     好了,Emit就介绍到这里。下面我们来看Emit技术实现我们的动态属性对象。

    动态属性对象实现
      我们需要的是一个可以把一系列键值对转换为一个类型的public property的
    工具,说白了就是一个函数。
      关于这个动态类型,我们得仔细考虑:
      1)它的public property都是来自输入的键值对;
      2)每个property名称都是键的名称;
      3)每个property都有get和set函数;
      4)我们需要在set函数里面发出修改前事件(prevSet)和修改完成事件(postSet)。
    最后一条又是我加的,因为我需要在属性值被修改前对新值进行检验,修改
    后提示有关界面(也为实现诸如MVP之类的模式提供支持)。
      这里的代码进行了简化,我们只处理属性值是字符串的情况。也没有(UITypeEditor)。

    这样做是为了不分散大家注意力。

      我们已经知道要创建一个什么样的动态类型了,现在来看代码:

    (这段代码来自项目exam2/utilities.cs)

    Code


       
      这段代码有很详细的注释,我就不废话了。
    代码下载:demo.zip
    后话:
      这里提供的代码,可以随意修改使用。只是希望各位将自己的心得,收获和困扰放到这里与大家分享。

  • 相关阅读:
    Linux下软件安装方法即路径设置
    maven和jdk版本不匹配
    jobTracker 和taskTracker
    任务调度quartz
    springside3.1.8打包
    给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组
    二进制求和
    数组中找到目标值,并返回其索引
    加1问题
    给定字符串返回最后一个单词的长度
  • 原文地址:https://www.cnblogs.com/sillyemperor/p/1295699.html
Copyright © 2011-2022 走看看