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. 使用history.back()返回此网页需要使用您之前输入的数据才能正常显示

    原因: 表单提交页面中使用了 session_start 函数.由于我们后退浏览的是缓存页,而该函数会强制当前页面不被缓存.解决:php: 此提示出现在一个POST提交的页面,点到其它页面后,通过Ja ...

  2. Yaconf-配置管理扩展

    1.下载yaconf安装包git clone https://github.com/laruence/yaconf.git2.目录切换至yaconf,编译生成so 文件(找到你的phpize位置) / ...

  3. 13 数组 Java内存分析 三种初始化

    Java内存分析 三种初始化 静态初始化 //静态初始化 创建+赋值 int[] a = {1,2,3}; Man[] mans = {new Man(1,1),new Man(2,2)}; 动态初始 ...

  4. 把EI科技 【载谈 Binomial Sum】 用人话说出来

    这个科技是用来 \(O(k+\log n)\) 求 \(\sum_{i=0}^n [x^i] f(x)p^i(x) \mod x^{k+1}\) 这个多项式的某些项数的线性组合 不过我只见过求第 $ ...

  5. pycharm远程调试、开发(详细操作)

    如果仅是远程开发,新建 ssh Interpreter 并 apply tools -> deployment -> browser remote host 即可 1.服务器侧准备 准备调 ...

  6. Java案例——统计字符串中各种字符出现的次数

    /*案例:统计各种字符在字符串中出现的次数 分析:只考虑三种字符类型的情况下(大写字母,小写字母,数字) 1.使用Scanner 类获取字符串数据 2.遍历字符串得到每一个字符 3.判断每一个字符是那 ...

  7. Docker修改默认IP

    Docker修改默认IP 删除原有配置 sudo systemctl stop docker sudo ip link set dev docker0 down sudo brctl delbr do ...

  8. UIautomatorviewer连接设备报错Unexpected error while obtaining UI hierarchy

    先来看下现象哈,点击sdk/tools下uiautomatorviever.bat,点击连接设备的图标,本以为就这么简单,那你就错了: 是不是看到这个瞬间心情就不好了,那么我们该怎么解决这个问题呢,归 ...

  9. [源码解析] TensorFlow 分布式环境(5) --- Session

    [源码解析] TensorFlow 分布式环境(5) --- Session 目录 [源码解析] TensorFlow 分布式环境(5) --- Session 1. 概述 1.1 Session 分 ...

  10. springboot的核心配置文件

    一.springboot主要配置文件种类 1.bootstrap (.yml或.properties) 2.application(.yml或.properties) 二.bootstrap与appl ...