TypeConverter 类,MSDN中的解释是提供一种将值的类型转换为其他类型以及访问标准值和子属性的统一方法。
先看一下例子,能够将字符串翻译成点结构的类型转换器
public class PointConverter : TypeConverter {
      public override bool CanConvertFrom(ITypeDescriptorContext context,Type sourceType) {
      if (sourceType == typeof(string)) {       return true;     }
      return base.CanConvertFrom(context, sourceType);
   }
   
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
      if (value is string) {
         string[] v = ((string)value).Split(new char[] {','});
         return new Point(int.Parse(v[0]), int.Parse(v[1]));
      }
      return base.ConvertFrom(context, culture, value);
   }
   public override object ConvertTo(ITypeDescriptorContext context,
      CultureInfo culture, object value, Type destinationType) { 
      if (destinationType == typeof(string)) {     return ((Point)value).X + "," + ((Point)value).Y;     }
      return base.ConvertTo(context, culture, value, destinationType);
   }
这个转换器可以实现字符串1,2到类型Point之间的转换。
举例,将对象转换为字符串
Point pt =new Point(1,2);
string point=TypeDescriptor.GetConverter(pt).ConvertToString(pt);
反过来,从字符串转换为对象
Point  pt = (Point)TypeDescriptor.GetConverter(typeof(Point)).ConvertFromString("1,2");

LLBL Gen中利用这个特性,将bit类型的1或0翻译为bool值true/false,将字符串的Y或N也翻译成bool值true/false
这样增强了编译时的类型检查,大大降低了出错的机会。

LLBL Gen 2.6中应用typeconverter。如下图所示,Suspended应用了System.Boolean的类型转换

Use different .NET type中列出了当前的应用类型。如果不需要应用类型转换,点击Reset to default。

LLBL Gen 3.1中应用typeconverter时,如下图所示

比如要给EmployeeStatus字符串类型应用typeconverter,用1表示在职,0表示已经离开公司,先设置它的.NET类型为boolean类型,然后到Field mappings中设置它的TypeConverter to use即可。

F7,生成项目源代码,通过查看DatabaseSpecific项目中的PersistenceInfoProviderCore类型,
看一下private void InitUserEntityMappings()的源代码

base.AddElementFieldMapping( "UserEntity", "Suspended", "Suspended", true, (int)SqlDbType.NVarChar, 1, 0, 0, false, "",  new Paradox.TypeConverters.BooleanStringConverter(), typeof(System.String), 2 );

倒数第三个参数,应用了BooleanStringConverter类型的转换器。

再来追踪一下,在ORM框架中,1/0是如何被转化为true/false的。
进入到Employee的属性EmployeeStatus
public virtual System.Boolean EmployeeStatus
{
            get { return (System.Int32)GetValue((int)EmployeeFieldIndex.EmployeeStatusId, true); }
            set    { SetValue((int)EmployeeFieldIndex.EmployeeStatusId, value); }
}

进入EntityBase2的SetValue方法
protected bool SetValue(int fieldIndex, object value)
{
           return SetValue(fieldIndex, value, true);
}

进入overload方法protected bool SetValue(int fieldIndex, object value, bool performDesyncForFKFields)
从这个方法,仍然没有找出如何应用typeConverter的。

再看一下EmployeeStatus的定义,在数据库中定义为bit,而在程序语言这里已经定义为bool,唯一发生转换的场景就是SELECT之后和INSERT/UPDATE之前,依照这个思路,到DynamicQueryEngine中寻找依据。
来看它的SELECT方法的实现
protected override void CreateSingleTargetInsertDQ(IEntityFieldCore[] fields, IFieldPersistenceInfo[] fieldsPersistenceInfo,

{

if(persistenceInfo.IsIdentity)
{
        newParameter = this.Creator.CreateParameter(field, persistenceInfo, _outputParameterDirection);
        query.AddParameterFieldRelation(field, newParameter, persistenceInfo.TypeConverterToUse);
看到从映射文件中读取的TypeConverterToUse,这似乎可以找到一些线索。右键点击AddParameterFieldRelation方法,选取菜单View Call Hierarchy
 
从Call Hierarchy窗口中,展开Implementations,可找到这个接口方法的实现类型,BatchActionQuery和Query.

进入BatchActionQuery中,方法定义为空
public IParameterFieldRelation AddParameterFieldRelation(IEntityFieldCore field, DbParameter parameter, TypeConverter typeConverterToUse)
        {
            return null;
        }

进入Query中的方法定义,看到在这里构造了一个ParameterFieldRelation对象,心中一点小小喜悦。

public IParameterFieldRelation AddParameterFieldRelation(IEntityFieldCore field, DbParameter parameter, TypeConverter typeConverterToUse)
        {
            IParameterFieldRelation relation = new ParameterFieldRelation(field, parameter, typeConverterToUse);
            if(_parameterFieldRelations==null)
            {
                _parameterFieldRelations = new List<IParameterFieldRelation>();
            }
            if(!_parameterFieldRelations.Contains(relation))
            {
                _parameterFieldRelations.Add(relation);
            }
            return relation;
        }

再看一下ParameterFieldRelation定义的注释信息,它的作用是定义query参数与field的关系。

Class to define the relation between a parameter of a query and a field. This relation is used to find back a related EntityFieldCore instance when an Output Parameter is found in a query so the value 
of the Output Parameter can be assigned to the related EntityField
这个类型定义有三个成员变量
private readonly IEntityFieldCore    _field;
private readonly DbParameter        _parameter;
private readonly TypeConverter        _typeConverterToUse;
有一个方法名叫Sync,方法体如下
public void Sync()
{
            if((_field!=null)&&(_parameter!=null))
            {
                object value = _parameter.Value;
#if !CF
                if(_typeConverterToUse!=null)
                {
                    value = _typeConverterToUse.ConvertFrom(null, null, value);
                }
#endif
                _field.ForcedCurrentValueWrite(value);
            }
}

Compact Framework框架无法使用typeconverter. 如果typeConverterToUse不为空,则转换传入的值,赋给属性
至此,我弄明白了typeconverter的使用方法,但是还不知道它被调用的时机。在方法名Sync上点击右键,Find All References,以查找所有的引用。

在Query.cs文件中,它有被使用到,方法如下
public void ReflectOutputValuesInRelatedFields()
{
            foreach(IParameterFieldRelation relation in _parameterFieldRelations)
            {
                // reflect value in related field object.
                relation.Sync();

继续在方法ReflectOutputValuesInRelatedFields上Find All References,以堆栈以上查找。
进入ActionQuery的Execute方法

public int Execute()
{
int returnValue = this.Command.ExecuteNonQuery();

if(returnValue>0)
    {
              // reflect new PK field values retrieved, if any, in their related fields. 
              this.ReflectOutputValuesInRelatedFields();
      }
再向上,在Execute方法上Find All References
进入到DataAccessAdapterBase的方法ExecuteActionQuery。
public virtual int ExecuteActionQuery(IActionQuery queryToExecute)
{
            TraceHelper.WriteLineIf(TraceHelper.PersistenceExecutionSwitch.TraceInfo, "DataAccessAdapterBase.ExecuteActionQuery", "Method Enter");
            try
            {
                PrepareQueryExecution(queryToExecute, false);
                return queryToExecute.Execute();
            }
            finally
            {
                CloseConnectionIfPossible();
                TraceHelper.WriteLineIf(TraceHelper.PersistenceExecutionSwitch.TraceInfo, "DataAccessAdapterBase.ExecuteActionQuery", "Method Exit");
            }
}
把这个片段分析倒过来,就是应用type converter的完整堆栈。

转载于:https://www.cnblogs.com/JamesLi2015/archive/2011/08/24/2151531.html

LLBL Gen 3.x 源代码追踪与解析 Type Converter 类型转换器相关推荐

  1. LLBL Gen Pro 设计器使用指南

    LLBL Gen Pro是个专业的ORM开发工具,官方网站是 http://www.llblgen.com/ LLBL Gen Pro是个支持多种持久层框架的ORM工具,如LLBL Gen Pro R ...

  2. 分享EOS加拿大的文章《REX——从源代码做技术解析》

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 已提议将丢失密钥恢复系统部署到EOS主网. 丢失密钥解决方案的最后一步已经在链上提出.最后一步是将丢失密钥解决方案智能合 ...

  3. ERP/MIS开发 LLBL Gen多表操作

    前一篇文章中提到,LLBL Gen对单个表的查询,这里再来分析一下LLBL Gen对多表的操作. Adapter模式,用到的变量adapter定义为DataAccessAdapter adapter= ...

  4. LLBL Gen Pro 3.X 下使用 Template 模版绑定(一)

    LLBL Gen Pro 3.X 下使用 Template 模版绑定(一) 前言 在 LLBL Gen3.X 下已经提供了多种生成模式供用户选择,但是有时候还是需要按照需求来改动 LLBL 生成的代码 ...

  5. ISO14443 Type A类型卡的防碰撞过程以及命令解析

    一.介绍 本博文介绍了PCD(Proximity Coupling Device)使用ISO14443-3 Type A协议检测匹配的PICC(Polling For Proximity Cards) ...

  6. iis设置允许或禁止访问的文件类型,以及能够解析的文件类型

    refs: https://blog.csdn.net/dofun333/article/details/74079760 设置iis能够解析的文件类型,比如".woff2"文件 ...

  7. 域名强制解析的常用类型

    域名解析是把域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站的一种服务.IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替IP地址标识站点地址.域名解析就是域名到IP地址的 ...

  8. Spring MVC自定义类型转换器Converter、参数解析器HandlerMethodArgumentResolver

    文章目录 一.前言 二.类型转换器Converter 1.自定义类型转换器 三.参数解析器 1.自定义分页参数解析器 2.自定义注解参数解析器 一.前言 Spring MVC源码分析相关文章已出: S ...

  9. FFMPEG之H264获取NALU并且解析其RBSP类型03

    FFMPEG之H264获取NALU并且解析其RBSP类型03 前言 FFMPEG之H264理论篇. 理论的就不多讲了,可以参考上面那篇文章,下面将给出两种版本,一种是我自己的,用C++方法实现,另一种 ...

最新文章

  1. 重磅福利!60篇近两年高影响因子环境污染微生态相关文献合集免费领取
  2. [POI2007]堆积木Klo
  3. 用AI击破传统行业痛点 “百度大脑行业创新论坛”将提7大行业解决方案
  4. linux之gdb基本调试命令和使用总结
  5. .sh文件是什么语言_FastDFS分布式文件系统的搭建安装
  6. 雷凌linux车机升级_绿老师学堂:15万合资车谁更“聪明”?体验思域/福克斯/雷凌车机...
  7. Stopwatch类的使用
  8. 算力单位TOPS,GPU处理能力(TFLOPS/TOPS),CPU能力MIPS ,片外内存与片内内存
  9. Android 11适配指南之系统相机拍照、打开相册
  10. c语言求闰年while,基础练习 闰年判断 c语言
  11. [人生感悟]在平凡中蜕变,我的2014
  12. 废品站老板切割金属罐体时发生爆炸致死
  13. 李永乐讲通信与计算机专业,哈工大通信与信息工程18考研经验分享
  14. 单片机:按键调节时钟
  15. JS的string方法
  16. Java并发编程的艺术-并发编程基础
  17. 图像处理 - 打开图片
  18. 微信域名网址强制跳转至浏览器打开指定app网页
  19. VB.Net 解决winForm界面卡死
  20. paypal pdt php 5.3,opencart经验分享-paypal的配置与PDT Token的获取 | SDT技术网

热门文章

  1. LeetCode —— 332. 重新安排行程(Python)
  2. 三层Dirichlet 过程(非参贝叶斯模型)-来自Machine Learning
  3. Exception in thread main java.lang.RuntimeException: org.apache.hadoop.security.AccessControlExcep
  4. extend()与append()的区别
  5. Docker学习一:Docker简介与安装
  6. [gstreamer] [002] porting from 0.10 to 1.0 knew how
  7. 计算机数学基础符号,《计算机数学基础(2)—离散数学》+谓词逻辑.doc
  8. win7临时文件_教你win7网页打开慢的应对办法
  9. php 模拟ip访问网页,curl模拟浏览器,ip,来源,进行网站采集的实现方法
  10. python 判断时间是否大于6点_python - 在dataframe中,如何检查时间增量是否大于一分钟?_pandas_酷徒编程知识库...