引言

最近在用Dapper处理Sqlite。映射模型的时候不喜欢用Attribute配置,希望用类似EF的Map来配置,所以粗略的实现了一个。

实现

首先是主体的配置辅助类型:

using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
using Dapper;
using DRapid.Utility.Linq.Expressions; namespace DRapid.Utility.Dapper.Map
{
public class InstanceMapper<T> : InstanceMapper
{
protected InstanceMapper()
: base(typeof(T))
{ } public static InstanceMapper<T> Config()
{
return new InstanceMapper<T>();
} public void MapColumn(string columnName, Expression<Func<T, object>> propertySelector)
{
var propertyName = ExpressionHelper.ReadMemberName(propertySelector);
MapColumn(columnName, propertyName);
}
} public class InstanceMapper : SqlMapper.ITypeMap
{
protected InstanceMapper(Type type)
{
_map = new CustomPropertyTypeMap(type, GetProperty);
_mapDic = new ConcurrentDictionary<string, PropertyInfo>();
_instanceType = type;
} private CustomPropertyTypeMap _map;
private Type _instanceType;
private ConcurrentDictionary<string, PropertyInfo> _mapDic; public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
return _map.FindConstructor(names, types);
} public ConstructorInfo FindExplicitConstructor()
{
return _map.FindExplicitConstructor();
} public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
return _map.GetConstructorParameter(constructor, columnName);
} public SqlMapper.IMemberMap GetMember(string columnName)
{
return _map.GetMember(columnName);
} public void MapColumn(string columnName, string propertyName)
{
_mapDic.AddOrUpdate(columnName,
key => _instanceType.GetProperty(propertyName),
(key, pro) => _instanceType.GetProperty(propertyName));
} private PropertyInfo GetProperty(Type type, string columnName)
{
PropertyInfo propertyInfo;
var result = _mapDic.TryGetValue(columnName, out propertyInfo);
return result ? propertyInfo : null;
} public void Apply()
{
SqlMapper.SetTypeMap(_instanceType, this);
} public static InstanceMapper Config(Type type)
{
return new InstanceMapper(type);
}
}
}

这里是其中引用的一个辅助方法的实现

        public static string ReadMemberName<T>(Expression<Func<T, object>> expression)
{
var body = expression.Body;
/*这里需要考虑转型表达式*/
if (body.NodeType == ExpressionType.Convert)
body = ((UnaryExpression) body).Operand;
Trace.Assert(body.NodeType == ExpressionType.MemberAccess, "表达式必须是成员访问或者是带转型的成员访问");
var accessMember = (MemberExpression) body;
return accessMember.Member.Name;
}

然后是一些链式调用的扩展支持

using System;
using System.Linq.Expressions; namespace DRapid.Utility.Dapper.Map
{
public static class InstanceMapperExtension
{
public static InstanceMapper<T> Use<T>(this InstanceMapper<T> mapper, string columnName, string propertyName)
{
mapper.MapColumn(columnName, propertyName);
return mapper;
} public static InstanceMapper<T> Use<T>(this InstanceMapper<T> mapper, string columnName,
Expression<Func<T, object>> propertySelector)
{
mapper.MapColumn(columnName, propertySelector);
return mapper;
}
}
}

调用

由于有静态访问入口,所以配置一般分布在各个类的静态构造函数中,从而防止重复配置。

所以,对于一个dto类型:

        public class PointInfo
{
public byte[] Detail { get; set; } public double Latitude { get; set; } public double Longitude { get; set; } public int Count { get; set; }
}

可以使用以下配置代码进行配置:

        InstanceMapper<PointInfo>.Config()
.Use("STATLG", s => s.Longitude)
.Use("STATLA", s => s.Latitude)
.Use("FREQUERYCOUNT", s => s.Count)
.Use("FREQDB", s => s.Detail)
.Apply();

结束。

为Dapper编写一个类似于EF的Map配置类的更多相关文章

  1. Java连接MySQL数据库。编写一个应用程序,在主类Test_4类中,通过JDBC访问stu数据库,显示t_student表中的内容(表结构见表1),显示效果自己设计。

    题目2:编写一个应用程序,在主类Test_4类中,通过JDBC访问stu数据库,显示t_student表中的内容(表结构见表1),显示效果自己设计.之后,可根据显示的内容进行某条记录的删除(以id为条 ...

  2. 编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容

    题目1:编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容--"chen","wang",&q ...

  3. property_自己编写一个读取Property文件的Util类

    读取property文件的Util类: 所需jar包: 编写PropertiesUtil类: package com.west.util.property; import java.io.InputS ...

  4. 16.按要求编写Java应用程序。 编写一个名为Test的主类,类中只有一个主方法; 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元素,每输出十个换一行;在主方法中定义一 个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。

    //分类 package com.bao; public class Shuchu { int[]yi=new int[50]; String[][]er=new String[10][10]; vo ...

  5. 按要求编写Java应用程序。 编写一个名为Test的主类,类中只有一个主方法; 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元素,每输出十个换一行;在主方法中定义一 个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。

    int[]x=new int [50]; char[][]y=new char[10][10]; int j=1,w=0; for(int i=0;i<50;i++) { x[i]=j; j+= ...

  6. 编写一个名为Test的主类,类中只有一个主方法; 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元素,每输出十个换一行;在主方法中定义一 个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。

    package liu0915; import java.util.Random; public class Test0915sz { public static void main(String[] ...

  7. 编写一个Filter,除继承HttpServlet类外还需要( )。

    A.继承Filter 类 B.实现Filter 接口 C.继承HttpFilter 类 D.实现HttpFilter接口 解答:B

  8. 【1】按照Django官网,编写一个web app 创建project/配置数据库

    1. Creating a project From the command line, cd into a directory where you'd like to store your code ...

  9. 13)编写一个子类SnakeCtrl来继承基类

    1)首先是创建子类SnakeCtrl 2)     添加那个SnakeCtrl子类 3)出来了SnakeCtrl的基本样子 4)简单实现: ①改编那个SnakeCtrl.h中的内容: #pragma ...

随机推荐

  1. Core Bluetooth Programming Guide

    https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth ...

  2. 一个关于如何创建类似于QQ客户端聊天窗口的模拟小项目

    对于不久之前学习到的一个有关的类似于QQ聊天框的模拟项目,对其中涉及到的知识在这里做一下总结. 首先,你要先创建一个客户端聊天框(取名为:ChatClient,它是你创建的类),这个类继承了Frame ...

  3. response小结(一)——用response向客户端输出中文数据(乱码问题分析)

    Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象,和代表响应的response对象.request和response对象既然代表请求和响应,那我们要 ...

  4. Objective-C 【多个对象内存管理(野指针&内存泄漏)】

    ------------------------------------------- 多个对象内存管理(野指针&内存泄漏) (注:这一部分知识请结合"单个对象内存管理"去 ...

  5. MVC 生成PDf表格并插入图片

    最近做的项目中有一个功能,将最终的个人信息生成PDF表格,并插入图片.对于没接触过的程序员来说回一片茫然,网上有多种生成PDf的方法,我给大家介绍一下我认为比较简单,好操作的一种. iTextShar ...

  6. PHP中常量

    PHP中常量 常量就是一种特殊的变量,PHP中的常量值一旦定义,在程序运行过程中不可更改,常量本身也不允许删除. 程序是用于解决现实问题,由两部分组成:代码,数据 常量的定义: 语法1: define ...

  7. PERL 脚本

    PERL: Practical Extraction and Report Language 参考文档 1.Perl 5 version 24.0 documentation

  8. Poj 3117 World Cup

    1.Link: http://poj.org/problem?id=3117 2.Content: World Cup Time Limit: 1000MS   Memory Limit: 65536 ...

  9. jquery实现全选、全不选、反选操作

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...

  10. DTcms列表隔行换色;loop自带行号

    <%loop cdr2 bcategoryList%> <%if(cdr2__loop__id==1)%> <a class="no-bg" href ...