using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Fast.Framework.Models; namespace Fast.Framework.Extensions
{ /// <summary>
/// 表达式扩展类
/// </summary>
public static class ExpressionExtensions
{
/// <summary>
/// 解析Sql
/// </summary>
/// <param name="expression">表达式</param>
/// <param name="options">选项</param>
/// <returns></returns>
public static SqlInfo ResolveSql(this Expression expression, SqlExpressionOptions options)
{
var ex = new SqlExpressionVisitor(options);
ex.Visit(expression);
return ex.sqlInfo;
}
} /// <summary>
/// 解析类型
/// </summary>
public enum ResolveType
{
/// <summary>
/// Sql字符串
/// </summary>
SqlString = 0, /// <summary>
/// 调用
/// </summary>
Call = 1, /// <summary>
/// 左相似
/// </summary>
LeftLike = 2, /// <summary>
/// 右相似
/// </summary>
RightLike = 3, /// <summary>
/// 相似
/// </summary>
Like = 4
} /// <summary>
/// 表达式映射
/// </summary>
public static class ExpressionMapper
{
/// <summary>
/// 表达式类型
/// </summary>
public static readonly Dictionary<ExpressionType, string> expressionTypes; /// <summary>
/// 方法调用
/// </summary>
public static readonly Dictionary<string, Action<SqlInfo, MethodCallExpression, Func<Expression, Expression>, Action<ResolveType>>> methodCall; /// <summary>
/// 转换
/// </summary>
public static readonly Action<MethodCallExpression, Func<Expression, Expression>, Action<ResolveType>> convert; /// <summary>
/// 构造方法
/// </summary>
static ExpressionMapper()
{
expressionTypes = new Dictionary<ExpressionType, string>()
{
{ExpressionType.Add,"+" },
{ExpressionType.Subtract,"-" },
{ExpressionType.Multiply,"*" },
{ExpressionType.Divide,"/" },
{ExpressionType.AndAlso,"AND" },
{ExpressionType.OrElse,"OR" },
{ExpressionType.Equal,"=" },
{ExpressionType.NotEqual,"<>" },
{ExpressionType.GreaterThan,">" },
{ExpressionType.LessThan,"<" },
{ExpressionType.GreaterThanOrEqual,">=" },
{ExpressionType.LessThanOrEqual,"<=" }
}; methodCall = new Dictionary<string, Action<SqlInfo, MethodCallExpression, Func<Expression, Expression>, Action<ResolveType>>>()
{
#region 聚合函数
{"Sum", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("SUM");
} },
{"Max", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("MAX");
} },
{"Min", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("MIN");
} },
{"Count", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("COUNT");
} },
{"Avg", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("AVG");
} },
#endregion #region 日期函数
{"GetDate", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
sql.SqlStack.Push("(");
sql.SqlStack.Push("GETDATE");
} },
{"Year", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("YEAR");
} },
{"Month", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("MONTH");
} },
{"Day", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("DAY");
} },
{"Current_Timestamp", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
sql.SqlStack.Push("(");
sql.SqlStack.Push("CURRENT_TIMESTAMP");
} },
{"Current_Date", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
sql.SqlStack.Push("(");
sql.SqlStack.Push("CURRENT_DATE");
} },
{"Current_Time", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
sql.SqlStack.Push("(");
sql.SqlStack.Push("CURRENT_TIME");
} },
#endregion #region 数学函数
{"Abs", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("ABS");
} },
{"Round", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[1]);
sql.SqlStack.Push(",");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("ROUND");
} },
#endregion #region 字符串函数
{"Contains", (sql,node,visit,call)=>
{
call(ResolveType.Like);
visit.Invoke(node.Arguments[0]);
call(ResolveType.SqlString);
sql.SqlStack.Push(" LIKE ");
visit.Invoke(node.Object);
} },
{"StartsWith", (sql,node,visit,call)=>
{
call(ResolveType.LeftLike);
visit.Invoke(node.Arguments[0]);
call(ResolveType.SqlString);
sql.SqlStack.Push(" LIKE ");
visit.Invoke(node.Object);
} },
{"EndsWith", (sql,node,visit,call)=>
{
call(ResolveType.RightLike);
visit.Invoke(node.Arguments[0]);
call(ResolveType.SqlString);
sql.SqlStack.Push(" LIKE ");
visit.Invoke(node.Object);
} },
{"Substring", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
if (node.Arguments.Count > 1)
{
visit.Invoke(node.Arguments[1]);
sql.SqlStack.Push(",");
}
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push(",");
visit.Invoke(node.Object);
sql.SqlStack.Push("(");
sql.SqlStack.Push("SUBSTRING");
} },
{"Replace", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[1]);
sql.SqlStack.Push(",");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push(",");
visit.Invoke(node.Object);
sql.SqlStack.Push("(");
sql.SqlStack.Push("REPLACE");
} },
{"ToUpper", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Object);
sql.SqlStack.Push("(");
sql.SqlStack.Push("UPPER");
} },
{"ToLower", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Object);
sql.SqlStack.Push("(");
sql.SqlStack.Push("LOWER");
} },
{"Trim", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Object);
sql.SqlStack.Push("(");
sql.SqlStack.Push("TRIM");
} },
#endregion #region 其它函数
{"Equals", (sql,node,visit,call)=>
{
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push(" = ");
visit.Invoke(node.Object);
} },
{"IsNull", (sql,node,visit,call)=>
{
sql.SqlStack.Push(")");
visit.Invoke(node.Arguments[1]);
sql.SqlStack.Push(",");
visit.Invoke(node.Arguments[0]);
sql.SqlStack.Push("(");
sql.SqlStack.Push("ISNULL");
visit.Invoke(node.Object);
} }
#endregion
};
}
} /// <summary>
/// Sql表达式访问
/// </summary>
public class SqlExpressionVisitor : ExpressionVisitor
{ /// <summary>
/// Sql信息
/// </summary>
public readonly SqlInfo sqlInfo; /// <summary>
/// 参数索引
/// </summary>
private readonly Dictionary<string, int> parameterIndex; /// <summary>
/// 成员信息
/// </summary>
private readonly Stack<MemberInfo> memberInfos; /// <summary>
/// 表达式选项
/// </summary>
private readonly SqlExpressionOptions options; /// <summary>
/// 解析类型
/// </summary>
private ResolveType resolveType; /// <summary>
/// 构造方法
/// </summary>
/// <param name="options">表达式选项</param>
public SqlExpressionVisitor(SqlExpressionOptions options, ResolveType resolveType = ResolveType.SqlString)
{
sqlInfo = new SqlInfo();
parameterIndex = new Dictionary<string, int>();
memberInfos = new Stack<MemberInfo>();
this.options = options;
this.resolveType = resolveType;
} /// <summary>
/// 访问
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
[return: NotNullIfNotNull("node")]
public override Expression Visit(Expression node)
{
//Console.WriteLine(node?.NodeType);
return base.Visit(node);
} /// <summary>
/// 访问Lambda
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitLambda<T>(Expression<T> node)
{
if (!options.IgnoreParameterExpression)
{
var index = 0;
foreach (var parameter in node.Parameters)
{
parameterIndex.Add(parameter.Name, index);
index++;
}
}
return Visit(node.Body);
} /// <summary>
/// 访问一元表达式
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitUnary(UnaryExpression node)
{
var memberExpression = (node as UnaryExpression).Operand as MemberExpression;
var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
var array = (sqlExpressionVisitor.Visit(memberExpression) as ConstantExpression).Value as object[];
return Visit(Expression.Constant(array.Length));
} /// <summary>
/// 访问二元表达式
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitBinary(BinaryExpression node)
{
if (node.NodeType == ExpressionType.ArrayIndex)
{
var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
var array = (sqlExpressionVisitor.Visit(node.Left) as ConstantExpression).Value as object[];
var value = array[Convert.ToInt32((sqlExpressionVisitor.Visit(node.Right) as ConstantExpression).Value)];
return VisitConstant(Expression.Constant(value));
}
else
{
if (!ExpressionMapper.expressionTypes.ContainsKey(node.NodeType))
{
throw new Exception($"暂不支持{node.NodeType}类型解析");
}
var op = ExpressionMapper.expressionTypes[node.NodeType];
if (node.Right.NodeType == ExpressionType.Constant && ((ConstantExpression)node.Right).Value == null)//判断null值
{
if (op == "=")
{
sqlInfo.SqlStack.Push(" IS NULL");
}
else if (op == "<>")
{
sqlInfo.SqlStack.Push(" IS NOT NULL");
}
}
else
{
if (node.Right is BinaryExpression && node.Right.NodeType == ExpressionType.Equal)
{
sqlInfo.SqlStack.Push(")");
Visit(node.Right);//右边带括号
sqlInfo.SqlStack.Push("(");
}
else
{
Visit(node.Right);//右边
}
sqlInfo.SqlStack.Push($" {op} ");//操作符
}
if (node.Left is BinaryExpression && node.Left.NodeType == ExpressionType.Equal)
{
sqlInfo.SqlStack.Push(")");
Visit(node.Left); //左边带括号
sqlInfo.SqlStack.Push("(");
}
else
{
Visit(node.Left); //左边
}
}
return node;
} /// <summary>
/// 访问索引
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitIndex(IndexExpression node)
{
return base.VisitIndex(node);
} /// <summary>
/// 访问参数
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitParameter(ParameterExpression node)
{
if (!options.IgnoreParameterExpression)
{
sqlInfo.SqlStack.Push($"p{parameterIndex[node.Name]}.");
}
return node;
} /// <summary>
/// 访问对象
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitNew(NewExpression node)
{
if (resolveType == ResolveType.SqlString)
{
for (int i = 0; i < node.Arguments.Count; i++)
{
var name = AddIdentifier(node.Members[i].IsDefined(typeof(ColumnAttribute)) ? node.Members[i].GetCustomAttribute<ColumnAttribute>().Name : node.Members[i].Name);
Visit(node.Arguments[i]);
var value = string.Join("", sqlInfo.SqlStack.ToList());
sqlInfo.NewKeyValues.Add(name, value);
sqlInfo.NewNames.Add(name);
sqlInfo.NewValues.Add(value);
sqlInfo.NewAssignMapper.Add($"{name} = {value}");
sqlInfo.NewAsMapper.Add($"{value} AS {name}");
sqlInfo.SqlStack.Clear();
}
}
else if (resolveType == ResolveType.Call)
{
var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call); var args = new List<object>();
foreach (var item in node.Arguments)
{
args.Add((sqlExpressionVisitor.Visit(item) as ConstantExpression).Value);
} var type = node.Type; object obj = null; if (type.IsGenericTypeDefinition)//泛型类
{
type = type.MakeGenericType(type.GetGenericArguments());
}
if (type.IsDefined(typeof(CompilerGeneratedAttribute)))//匿名对象
{
var argsTypes = args.Select(s => s?.GetType()).ToList().GetTypeDefaultValue();
obj = Activator.CreateInstance(type, argsTypes.ToArray());
for (int i = 0; i < node.Members.Count; i++)
{
var member = node.Members[i];
type.GetField($"<{member.Name}>i__Field", BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance).SetValue(obj, args[i]);
}
}
else
{
obj = Activator.CreateInstance(type, args.ToArray());
}
return VisitConstant(Expression.Constant(obj));
}
return node;
} /// <summary>
/// 访问列表初始化
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitListInit(ListInitExpression node)
{
var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call); var args = new List<object>();
args.Add((sqlExpressionVisitor.Visit(node.NewExpression) as ConstantExpression).Value); var type = node.Type;
if (type.IsGenericTypeDefinition)
{
type = type.MakeGenericType(type.GetGenericArguments());
}
var list = Activator.CreateInstance(type, args.ToArray());
foreach (var item in node.Initializers)
{
var args2 = new List<object>();
foreach (var item2 in item.Arguments)
{
args2.Add((sqlExpressionVisitor.Visit(item2) as ConstantExpression).Value);
}
item.AddMethod.Invoke(list, args2.ToArray());
}
if (resolveType == ResolveType.SqlString)
{
return VisitConstant(Expression.Constant(string.Join(",", list)));
} return VisitConstant(Expression.Constant(list));
} /// <summary>
/// 访问对象数组
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitNewArray(NewArrayExpression node)
{
var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call); var array = Array.CreateInstance(node.Type.GetElementType(), node.Expressions.Count); for (int i = 0; i < array.Length; i++)
{
array.SetValue((sqlExpressionVisitor.Visit(node.Expressions[i]) as ConstantExpression).Value, i);
} if (resolveType == ResolveType.SqlString)
{
return VisitConstant(Expression.Constant(string.Join(",", array as object[])));
} return VisitConstant(Expression.Constant(array));
} /// <summary>
/// 访问方法
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (ExpressionMapper.methodCall.ContainsKey(node.Method.Name) && resolveType == ResolveType.SqlString)
{
ExpressionMapper.methodCall[node.Method.Name].Invoke(sqlInfo, node, e => Visit(e), (type) =>
{
resolveType = type;//回调设置类型
});
}
else
{
var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
var args = new List<object>();
foreach (var item in node.Arguments)
{
args.Add((sqlExpressionVisitor.Visit(item) as ConstantExpression).Value);
}
object obj = null;
if (node.Object == null)
{
obj = this;
}
else
{
obj = (sqlExpressionVisitor.Visit(node.Object) as ConstantExpression).Value;
}
var value = node.Method.Invoke(obj, args.ToArray());
resolveType = ResolveType.SqlString;
return Visit(Expression.Constant(value));
}
return node;
} /// <summary>
/// 访问成员初始化
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
protected override Expression VisitMemberInit(MemberInitExpression node)
{
var expressions = (node.Reduce() as BlockExpression).Expressions.Skip(1).SkipLast(1).ToList();//去除不需要的表达式; if (resolveType == ResolveType.SqlString)
{
for (int i = 0; i < expressions.Count; i++)
{
var binaryExpression = (BinaryExpression)expressions[i];
Visit(binaryExpression.Right);
var name = AddIdentifier(node.Bindings[i].Member.IsDefined(typeof(ColumnAttribute)) ? node.Bindings[i].Member.GetCustomAttribute<ColumnAttribute>().Name : node.Bindings[i].Member.Name);
var value = string.Join("", sqlInfo.SqlStack.ToList());
sqlInfo.NewKeyValues.Add(name, value);
sqlInfo.NewNames.Add(name);
sqlInfo.NewValues.Add(value);
sqlInfo.NewAssignMapper.Add($"{name} = {value}");
sqlInfo.NewAsMapper.Add($"{value} AS {name}");
sqlInfo.SqlStack.Clear();
}
}
else if (resolveType == ResolveType.Call)
{
var sqlExpressionVisitor = new SqlExpressionVisitor(options, ResolveType.Call);
var obj = (sqlExpressionVisitor.Visit(node.NewExpression) as ConstantExpression).Value;
for (int i = 0; i < expressions.Count; i++)
{
if (node.Bindings[i].Member.MemberType == MemberTypes.Field)
{
var fields = (FieldInfo)node.Bindings[i].Member;
fields.SetValue(obj, (sqlExpressionVisitor.Visit((expressions[i] as BinaryExpression).Right) as ConstantExpression).Value);
}
if (node.Bindings[i].Member.MemberType == MemberTypes.Property)
{
var propertyInfo = (PropertyInfo)node.Bindings[i].Member;
propertyInfo.SetValue(obj, (sqlExpressionVisitor.Visit((expressions[i] as BinaryExpression).Right) as ConstantExpression).Value);
}
}
return VisitConstant(Expression.Constant(obj));
}
return node;
} /// <summary>
/// 访问成员
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitMember(MemberExpression node)
{
memberInfos.Push(node.Member);
if (node.Expression == null && node.NodeType == ExpressionType.MemberAccess)
{
return Visit(Expression.Constant(null));//子表达式为空但有成员处理
}
if (node.Expression.NodeType == ExpressionType.Parameter)
{
if (node.Member.IsDefined(typeof(ColumnAttribute)))
{
sqlInfo.SqlStack.Push(AddIdentifier(node.Member.GetCustomAttribute<ColumnAttribute>().Name));
}
else
{
sqlInfo.SqlStack.Push(AddIdentifier(node.Member.Name));
}
}
return Visit(node.Expression);
} /// <summary>
/// 访问常量
/// </summary>
/// <param name="node">节点</param>
/// <returns></returns>
protected override Expression VisitConstant(ConstantExpression node)
{
var value = node.Value;
if (value != null && value.GetType().FullName.EndsWith("c__DisplayClass0_0"))
{
foreach (var member in memberInfos)
{
if (member.MemberType == MemberTypes.Field)
{
var fieldInfo = (FieldInfo)member;
value = fieldInfo.GetValue(value);
}
else if (member.MemberType == MemberTypes.Property)
{
var propertyInfo = (PropertyInfo)member;
value = propertyInfo.GetValue(value);
}
}
} if (resolveType != ResolveType.Call)
{
if (value != null && value.GetType().Equals(typeof(DateTime)))
{
value = Convert.ToDateTime(value).ToString(options.DateTimeFormat);//格式化日期类型
}
if (memberInfos.Count > 0)
{
var parameterName = Guid.NewGuid().ToString().Replace("-", "");
sqlInfo.SqlStack.Push($"{options.ParameterNotation}{parameterName}");
sqlInfo.SqlParameters.Add(parameterName, AddWildcard(value));
}
else
{
value = AddQuotes(AddWildcard(value));
sqlInfo.SqlStack.Push(Convert.ToString(value));
}
} //最后一个节点初始化
memberInfos.Clear();
return Expression.Constant(value);//返回新的常量表达式
} #region 私有公共方法 /// <summary>
/// 添加引号
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
private static object AddQuotes(object value)
{
if (value == null)
{
return null;
}
var type = value.GetType();
if (type.Equals(typeof(char)) || type.Equals(typeof(string)) || type.Equals(typeof(DateTime)))
{
return $"'{value}'";
}
return value;
} /// <summary>
/// 添加识别符
/// </summary>
/// <param name="name">名称</param>
/// <returns></returns>
private string AddIdentifier(string name)
{
if (string.IsNullOrWhiteSpace(options.Identifier))
{
return name;
}
return options.Identifier.Insert(1, name);
} /// <summary>
/// 添加通配符
/// </summary>
/// <param name="value">值</param>
/// <returns></returns>
private object AddWildcard(object value)
{
if (resolveType == ResolveType.LeftLike)
{
return $"%{value}";
}
else if (resolveType == ResolveType.RightLike)
{
return $"{value}%";
}
else if (resolveType == ResolveType.Like)
{
return $"%{value}%";
}
return value;
}
#endregion }
}

https://gitee.com/China-Mr-zhong/Fast.Framework 欢迎Star

玩转NET Expression的更多相关文章

  1. 零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异

    原文:零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异 本次要针对Disabled以及Hidden作 ...

  2. [C#] 了解过入口函数 Main() 吗?带你用批处理玩转 Main 函数

    了解过入口函数 Main() 吗?带你用批处理玩转 Main 函数 目录 简介 特点 方法的参数 方法的返回值 与批处理交互的一个示例 简介 我们知道,新建一个控制台应用程序的时候,IDE 会同时创建 ...

  3. 我这么玩Web Api(二):数据验证,全局数据验证与单元测试

    目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试   一.模型状态 - ModelState 我理解 ...

  4. [小北De编程手记] : Lesson 05 玩转 xUnit.Net 之 从Assert谈UT框架实践

    这一篇,本文会介绍一下基本的断言概念,但重点会放在企业级单元测试的相关功能上面.下面来跟大家分享一下xUnit.Net的断言,主要涉及到以下内容: 关于断言的概念 xUnit.Net常用的断言 关于单 ...

  5. 玩转spring boot——properties配置

    前言 在以往的java开发中,程序员最怕大量的配置,是因为配置一多就不好统一管理,经常出现找不到配置的情况.而项目中,从开发测试环境到生产环境,往往需要切换不同的配置,如测试数据库连接换成生产数据库连 ...

  6. 转载Entity Framework 4.1 DbContext使用记之三——如何玩转实体的属性值?

    Entity Framework 4.1 DbContext使用记之一——如何查找实体? DbSet.Find函数的使用与实现 Entity Framework 4.1 DbContext使用记之二— ...

  7. 玩转PHP中的正则表达式

    玩转PHP中的正则表达式 检验用户输入.解析用户输入和文件内容,以及重新格式化字符串 级别: 中级 正则表达式提供了一种处理文本的强大方法.使用正则表达式,您可以对用户输入进行复杂的检验.解析用户输入 ...

  8. 工欲善其事,必先利其器 软件工具开发关键词 protractor自动化测试工具 RegexBuddy正则 CodeSmith,LightSwitch:代码生成 CheatEngine:玩游戏修改内存值必备神器 ApkIDE:Android反编译工具 Reflector:反编译dll动态链接库

    工欲善其事,必先利其器 本文版权归翟士丹(Stan Zhai)和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利. 原文地址:http ...

  9. SQL Expression Language Tutorial 学习笔记二

    11. Using Textual SQL 直接使用 SQL 如果实在玩不转, 还是可以通过 test() 直接写 SQL. In [51]: s = text( ...: "SELECT ...

随机推荐

  1. thinkphp 框架自带搜索+分页+搜索标红

    ..........控制器方法 public function index() { //接受搜索关键字 $word=input('word'); $where=[]; if (!empty($word ...

  2. 微服务从代码到k8s部署应有尽有大结局(k8s部署)

    我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...

  3. 『现学现忘』Docker基础 — 26、Docker镜像分层的理解

    目录 1.分层的镜像 2.加深理解 3.特别说明 1.分层的镜像 我们可以去下载一个镜像,注意观察下载的日志输出,可以看到Docker的镜像是一层一层的在下载. 思考:为什么Docker镜像要采用这种 ...

  4. 线程池的极简用法——内置线程池multiprocessing

    大家好,今天博主来分享一个线程池的小捷径--内置线程池的使用方法 一.背景 说道多线程,对变成层有了解的小伙伴一定不陌生,虽然不知道是什么但是也会从各大网站.面试分享等途径听说过.这里就不做过多的介绍 ...

  5. Nginx高并发实现原理以及常用的优化手段

    Nginx 是如何实现高并发的? 异步,非阻塞,使用了epoll 和大量的底层代码优化. 如果一个server采用一个进程负责一个request的方式,那么进程数就是并发数.正常情况下,会有很多进程一 ...

  6. Ubuntu 16.04 更改系统语言为简体中文

    镜像下载.域名解析.时间同步请点击阿里巴巴开源镜像站 一.安装时报错 原因:以访客的身份进入的会报错,改为管理员进入即可. ps:有时候往往一点小细节也会造成大问题,但是我们要善于排错. 注:可以看到 ...

  7. Arch Linux 安装 Anbox

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 Anbox 介绍 Anbox 是一个可以在 GNU/Linux 发行版上运行 Android App 的容器,是一个开源兼容层. 其工作原理是在 ...

  8. RabbitMQ Go客户端教程3——发布/订阅

    本文翻译自RabbitMQ官网的Go语言客户端系列教程,本文首发于我的个人博客:liwenzhou.com,教程共分为六篇,本文是第三篇--发布/订阅. 这些教程涵盖了使用RabbitMQ创建消息传递 ...

  9. w3af漏扫的基本使用

    一.安装 apt安装 apt-get update apt-get install -y w3af 出现无法定位软件包 源码安装 sudo apt-get install git sudo apt-g ...

  10. 查找bug的一些经验总结

    项目开发中遇到的bug解决经验总结 今天在项目开发中遇到了两个很难解决的bug,我把我的思路记录下来,以供之后遇到bug时,提供一些思路: 编译通过,但总结"core dumped" ...