为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 ...
随机推荐
- jQuery API 3.1.0 速查表-打印版
jQuery API 3.1.0 速查表-打印图,(API来自:http://jquery.cuishifeng.cn/index.html)
- 北大ACM(POJ1753-Flip Game)
Question:http://poj.org/problem?id=1753 问题点:穷举. #include <iostream> using namespace std; ][];/ ...
- 制作BibTex文件
上一篇日志中讲到了在LaTeX中使用BibTex管理参考文献,这篇日志具体总结下如何制作BibTex文件. 制作BibTex文件,主要有以下几种方法: 手工制作: 直接从期刊数据库中下载: 借助Goo ...
- crackme_zapline分析
[破文标题]crackme_zapline 分析 [破文作者]CloAk [作者邮箱]@qq.com [作者主页] [破解工具]OD,... [破解平台]Windows --------------- ...
- Swift使用闭包表达式
Swift中的闭包表达式很灵活,其标准语法格式如下:{ (参数列表) ->返回值类型 in 语句组}其中,参数列表与函数中的参数列表形式一样,返回值类型类似于函数中的返回值类型,但不同的是 ...
- 在windows7中使用计划任务命令SCHTASKS查询计划任务失败的解决方案
造成这种原因是因为编码问题: 因此需要修改编码:chcp schtasks.exe /query 会报错 错误: 无法加载列资源. 修改编码为936为436就可以允许啦,但是中文不不能显示啦. ...
- jQuery中的getter和setter方法
1.attr()方法是jQuery中用于HTML属性的getter/setter.一个相关函数是removeAttr(). 2.css()方法和attr()方法很类似,只是css()方法作用于元素的c ...
- 【leetcode】8. String to Integer (atoi)
题目描述: Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input ...
- [ZZ+CH] Html5 canvas+js 时钟
总之新Blog入驻以后,又开始老习惯,到处折腾自定义的空间,放些东西. 想起以前大一的时候做过一个Javascript的时间显示器,现在想做一个时钟,当然现在老奸巨猾,会先去看一看有前辈写过没. 前辈 ...
- jquery文字左右滚动
实现jquery文字左右滚动 <div class="fl">中奖名单:</div> <div class="scrollText" ...