2881099 bf72bf423c ## v0.3.25
- 修复 全局过滤器一个赋值低级错误;
- 增加 IFreeSql<TMark> 空接口,现实多个 IFreeSql 注入使用,使用泛型标识区分;
2019-03-23 02:11:18 +08:00

91 lines
3.3 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace FreeSql {
internal class Utils {
internal static Action<FluentDataFilter> _globalDataFilter;
static ConcurrentDictionary<Type, Delegate> _dicSetRepositoryDataFilterApplyDataFilterFunc = new ConcurrentDictionary<Type, Delegate>();
static ConcurrentDictionary<Type, ConcurrentDictionary<string, bool>> _dicSetRepositoryDataFilterConvertFilterNotExists = new ConcurrentDictionary<Type, ConcurrentDictionary<string, bool>>();
internal static void SetRepositoryDataFilter(object repos, Action<FluentDataFilter> scopedDataFilter) {
if (scopedDataFilter != null) {
SetRepositoryDataFilter(repos, null);
}
if (scopedDataFilter == null) {
scopedDataFilter = _globalDataFilter;
}
if (scopedDataFilter == null) return;
using (var globalFilter = new FluentDataFilter()) {
scopedDataFilter(globalFilter);
var type = repos.GetType();
Type entityType = (repos as IRepository).EntityType;
if (entityType == null) throw new Exception("FreeSql.Repository 设置过滤器失败,原因是对象不属于 IRepository");
var notExists = _dicSetRepositoryDataFilterConvertFilterNotExists.GetOrAdd(type, t => new ConcurrentDictionary<string, bool>());
var newFilter = new Dictionary<string, LambdaExpression>();
foreach (var gf in globalFilter._filters) {
if (notExists.ContainsKey(gf.name)) continue;
LambdaExpression newExp = null;
var filterParameter1 = Expression.Parameter(entityType, gf.exp.Parameters[0].Name);
try {
newExp = Expression.Lambda(
typeof(Func<,>).MakeGenericType(entityType, typeof(bool)),
new ReplaceVisitor().Modify(gf.exp.Body, filterParameter1),
filterParameter1
);
} catch {
notExists.TryAdd(gf.name, true); //防止第二次错误
continue;
}
newFilter.Add(gf.name, newExp);
}
if (newFilter.Any() == false) return;
var del = _dicSetRepositoryDataFilterApplyDataFilterFunc.GetOrAdd(type, t => {
var reposParameter = Expression.Parameter(type);
var nameParameter = Expression.Parameter(typeof(string));
var expressionParameter = Expression.Parameter(
typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(entityType, typeof(bool)))
);
return Expression.Lambda(
Expression.Block(
Expression.Call(reposParameter, type.GetMethod("ApplyDataFilter", BindingFlags.Instance | BindingFlags.NonPublic), nameParameter, expressionParameter)
),
new[] {
reposParameter, nameParameter, expressionParameter
}
).Compile();
});
foreach (var nf in newFilter) {
del.DynamicInvoke(repos, nf.Key, nf.Value);
}
newFilter.Clear();
}
}
}
class ReplaceVisitor : ExpressionVisitor {
private ParameterExpression parameter;
public Expression Modify(Expression expression, ParameterExpression parameter) {
this.parameter = parameter;
return Visit(expression);
}
protected override Expression VisitMember(MemberExpression node) {
if (node.Expression?.NodeType == ExpressionType.Parameter)
return Expression.Property(parameter, node.Member.Name);
return base.VisitMember(node);
}
}
}