为Dapper编写一个类似于EF的Map配置类
引言
最近在用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配置类的更多相关文章
- Java连接MySQL数据库。编写一个应用程序,在主类Test_4类中,通过JDBC访问stu数据库,显示t_student表中的内容(表结构见表1),显示效果自己设计。
题目2:编写一个应用程序,在主类Test_4类中,通过JDBC访问stu数据库,显示t_student表中的内容(表结构见表1),显示效果自己设计.之后,可根据显示的内容进行某条记录的删除(以id为条 ...
- 编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容
题目1:编写一个应用程序,在主类Test1类中,创建两个链表List<E>对象,分别存储通过键盘输入的字符串内容--"chen","wang",&q ...
- property_自己编写一个读取Property文件的Util类
读取property文件的Util类: 所需jar包: 编写PropertiesUtil类: package com.west.util.property; import java.io.InputS ...
- 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 ...
- 按要求编写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+= ...
- 编写一个名为Test的主类,类中只有一个主方法; 在主方法中定义一个大小为50的一维整型数组,数组名为x,数组中存放着{1, 3,5,…,99}输出这个数组中的所有元素,每输出十个换一行;在主方法中定义一 个大小为10*10的二维字符型数组,数组名为y,正反对角线上存的是‘*’,其余 位置存的是‘#’;输出这个数组中的所有元素。
package liu0915; import java.util.Random; public class Test0915sz { public static void main(String[] ...
- 编写一个Filter,除继承HttpServlet类外还需要( )。
A.继承Filter 类 B.实现Filter 接口 C.继承HttpFilter 类 D.实现HttpFilter接口 解答:B
- 【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 ...
- 13)编写一个子类SnakeCtrl来继承基类
1)首先是创建子类SnakeCtrl 2) 添加那个SnakeCtrl子类 3)出来了SnakeCtrl的基本样子 4)简单实现: ①改编那个SnakeCtrl.h中的内容: #pragma ...
随机推荐
- Ehcache(2.9.x) - API Developer Guide, Cache Manager Event Listeners
About CacheManager Event Listeners CacheManager event listeners allow implementers to register callb ...
- jquery之css()改变字体大小,颜色,背景色
转: <script type="text/javascript"> $(document).ready(function() { $("#f ...
- Win7 IIS (HTTP Error 500.21 - Internal Server Error)解决
今天在测试网站的时候,在浏览器中输入http://localhost/时,发生如下错误: HTTP Error 500.21 - Internal Server Error Handler " ...
- 第二十九篇、CoreAnimation的使用
使用的的三个步骤 1.初始化演员 2.设置好剧情 3.播放 主要类: CALayer // 绘图部分 CABaseAnimation // 基本动画(缩放,移动) CAKeyframeAnimatio ...
- PHP自定义日期英文格式 Feb 11,2015
背景:[PHP小工具]项目中,经常会要求多版本语言支持,而日期也是必不可少的组成元素. 英文日期书写顺序分英式和美式,举例如. 美国:月日年(January 8th,2014 或 January 8, ...
- (转)Linux下tomcat JVM内存设置步骤
java.lang.OutOfMemoryError: PermGen space java.lang.OutOfMemoryError: Java heap space -------------- ...
- day 0.
/* 嗯 就要结束了. OI生涯 2015.12-2016.11. 认识了很多人. 然后我这个学渣跟你们混在一起 感觉自卑至极啊. 好了 先不说这些伤心的话. Gryz小伙伴儿们NOIP RP++吧. ...
- 【转载】学习C++和编程的几个要点
1.把C++当成一门新的语言学习(和C没啥关系!真的.):2.看<ThinkingIn C++>,不要看<C++变成死相>:3.看<The C++ Programming ...
- windows下tomcat切割日志按照日期输出
windows下tomcat默认不会把应用的日志信息输出在日志文件中的,只会在控制台打印. 解决方法: 1,下载工具cronolog-1.6.1-win32.zip,并解压. 2,把cronolog. ...
- mysql配置优化测试
http://bjlfp.blog.163.com/blog/static/77368461201211695924524/ 感觉真不错啊.观察几天看看