You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
7.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace Common
{
/// <summary>
/// 脏字过滤委托实现
/// </summary>
/// <typeparam name="T"></typeparam>
public static class StrFilteFun<T>
{
/// <summary>
/// 脏字过滤委托
/// </summary>
public static Func<T, string[], T> FilterCode = StrFilteFun<T>.Generate();
private static T FilterCodeJump(T t, string[] s) => FilterCode(t, s);
/// <summary>
/// 循环处理
/// </summary>
/// <param name="collection"></param>
/// <param name="loopVar"></param>
/// <param name="loopContent"></param>
/// <returns></returns>
public static Expression ForEach(Expression collection, ParameterExpression loopVar, Expression loopContent)
{
var elementType = loopVar.Type;
var enumerableType = typeof(IEnumerable<>).MakeGenericType(elementType);
var enumeratorType = typeof(IEnumerator<>).MakeGenericType(elementType);
var enumeratorVar = Expression.Variable(enumeratorType, "enumerator");
var getEnumeratorCall = Expression.Call(collection, enumerableType.GetMethod("GetEnumerator"));
var enumeratorAssign = Expression.Assign(enumeratorVar, getEnumeratorCall);
// The MoveNext method's actually on IEnumerator, not IEnumerator<T>
var moveNextCall = Expression.Call(enumeratorVar, typeof(IEnumerator).GetMethod("MoveNext"));
var breakLabel = Expression.Label("LoopBreak");
var loop = Expression.Block(new[] { enumeratorVar },
enumeratorAssign,
Expression.Loop(
Expression.IfThenElse(
Expression.Equal(moveNextCall, Expression.Constant(true)),
Expression.Block(new[] { loopVar },
Expression.Assign(loopVar, Expression.Property(enumeratorVar, "Current")),
loopContent
),
Expression.Break(breakLabel)
),
breakLabel)
);
return loop;
}
public static Expression For(ParameterExpression loopVar, Expression initValue, Expression condition, Expression increment, Expression loopContent)
{
var initAssign = Expression.Assign(loopVar, initValue);
var breakLabel = Expression.Label("LoopBreak");
var loop = Expression.Block(new[] { loopVar },
initAssign,
Expression.Loop(
Expression.IfThenElse(
condition,
Expression.Block(
loopContent,
increment
),
Expression.Break(breakLabel)
),
breakLabel)
);
return loop;
}
/// <summary>
///委托过滤实现
/// </summary>
/// <returns></returns>
public static Func<T, string[], T> Generate()
{
var type = typeof(T);
var instance = Expression.Parameter(type);
var strArray = Expression.Parameter(typeof(string[]));
var returnLable = Expression.Label(type);
if (type == typeof(string))//数类型是string
return Expression.Lambda<Func<T, string[], T>>(
Expression.Block(
Expression.Call(StrFilteTools._StrFilter, instance, strArray)
), instance, strArray).Compile();
List<Expression> expressions = new List<Expression>();
//数据类型是list
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IList<>) || type.GetInterfaces().ToList().Where(e => e.IsGenericType && e.GetGenericTypeDefinition() == typeof(IList<>)).Any())
{
var loopVar = Expression.Parameter(typeof(int));
var loopContent = Expression.Assign(Expression.MakeIndex(instance, type.GetProperty("Item"), new[] { loopVar }), Expression.Call(typeof(StrFilteFun<>).MakeGenericType(type.GetGenericArguments()[0]).GetMethod(nameof(FilterCodeJump), BindingFlags.NonPublic | BindingFlags.Static), Expression.MakeIndex(instance, type.GetProperty("Item"), new[] { loopVar }), strArray));
var @for = For(loopVar, Expression.Constant(0), Expression.LessThan(loopVar, Expression.Property(instance, type.GetProperty("Count"))), Expression.PostIncrementAssign(loopVar), loopContent);
return Expression.Lambda<Func<T, string[], T>>(Expression.Block(
@for
, (Expression)Expression.Return(returnLable, instance)
, (Expression)Expression.Label(returnLable, instance)
), instance, strArray).Compile();
}
var pros = type.GetProperties();
var fieds = type.GetFields();
foreach (var item in pros)
{
try
{
///list 有属性是list<T>的情况
///
var member = Expression.Property(instance, item);
if (item.PropertyType == typeof(string) || item.PropertyType == typeof(List<string>) || item.PropertyType.IsGenericType && item.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>) || item.PropertyType.GetInterfaces().ToList().Where(e => e.IsGenericType && e.GetGenericTypeDefinition() == typeof(IEnumerable<>)).Any())
{
var call = Expression.Call(typeof(StrFilteFun<>).MakeGenericType(item.PropertyType).GetMethod(nameof(FilterCodeJump), BindingFlags.NonPublic | BindingFlags.Static), member, strArray);
var ifNotNull = Expression.IfThen(Expression.NotEqual(member, Expression.Constant(null, item.PropertyType)), Expression.Assign(member, call));
expressions.Add(ifNotNull);
}
}
catch { }
}
foreach (var item in fieds)//
{
try
{
if (item.FieldType == typeof(string))
{
var member = Expression.Field(instance, item);
var ifNotNull = Expression.IfThen(Expression.NotEqual(member, Expression.Constant(null, typeof(string))), Expression.Assign(member, Expression.Call(StrFilteTools._StrFilter, member, strArray)));
expressions.Add(ifNotNull);
}
}
catch { }
}
expressions.Add(Expression.Return(returnLable, instance));
expressions.Add(Expression.Label(returnLable, instance));
return Expression.Lambda<Func<T, string[], T>>(Expression.Block(expressions.ToArray()), instance, strArray).Compile();
}
}
/// <summary>
///脏字过滤
/// </summary>
public static class StrFilteTools
{
/// <summary>
/// 脏字数据List
/// </summary>
public static MethodInfo _StrFilter = typeof(StrFilteTools).GetMethod(nameof(StrFilter), BindingFlags.Static | BindingFlags.Public);
/// <summary>
/// 批量数据过滤
/// </summary>
/// <param name="value">要过滤操作的字符串</param>
/// <param name="Filterlist">过滤脏字列表</param>
/// <returns></returns>
public static string StrFilter(string value, string[] Filterlist)
{
var v = value;
foreach (var item in Filterlist)
{
if (!item.IsNull())
{
v = v.Replace(item, "*");
}
}
return v;
}
}
}