public static class ValueGetter
{
public static object Get(Type objType, Type valueType, PropertyInfo info)
{
var bodyExp = Expression.Call(
typeof(ValueGetter<,,>).MakeGenericType(objType, info.PropertyType, valueType),
nameof(ValueGetter<object, object, object>.GetGetter),
Array.Empty<Type>(),
Expression.Constant(info));
var finalExp = Expression.Lambda<Func<object>>(bodyExp);
var func = finalExp.Compile();
var re = func.Invoke();
return re;
}
public static object Get(Type objType, PropertyInfo info)
{
var bodyExp = Expression.Call(typeof(ValueGetter<>).MakeGenericType(objType),
nameof(ValueGetter<object>.GetGetter),
Array.Empty<Type>(),
Expression.Constant(info));
var finalExp = Expression.Lambda<Func<object>>(bodyExp);
var func = finalExp.Compile();
var re = func.Invoke();
return re;
}
internal static SwitchCase CreateGetterCase<TTargetObject, TTargetValue>(PropertyInfo propertyInfo)
{
var sourceObjExp = Expression.Parameter(typeof(TTargetObject), "sourceObj");
var finalExp =
Expression.Lambda<Func<TTargetObject, TTargetValue>>(
Expression.Convert(Expression.Property(sourceObjExp, propertyInfo), typeof(TTargetValue)),
sourceObjExp);
var getter = finalExp.Compile();
var caseExp = Expression.Constant(propertyInfo);
return Expression.SwitchCase(Expression.Constant(getter), caseExp);
}
internal static Func<PropertyInfo, Func<TTargetObject, TTargetValue>> CreateGetter<TTargetObject, TTargetValue>(
IEnumerable<PropertyInfo> propertyInfos,
Func<PropertyInfo, SwitchCase> caseFactory)
{
var pExp = Expression.Parameter(typeof(PropertyInfo), "info");
var cases = propertyInfos.Select(caseFactory);
var switchExp =
Expression.Switch(pExp,
Expression.Constant(null,
typeof(Func<TTargetObject, TTargetValue>)),
null,
cases);
var funcExp = Expression.Lambda<Func<PropertyInfo, Func<TTargetObject, TTargetValue>>>(switchExp, pExp);
var re = funcExp.Compile();
return re;
}
}
public static class ValueGetter<TTargetObject, TPropertyValue, TTargetValue>
{
private static readonly Func<PropertyInfo, Func<TTargetObject, TTargetValue>> Finder;
static ValueGetter()
{
var propertyInfos = typeof(TTargetObject).GetRuntimeProperties()
.Where(x => x.CanRead)
.Where(x => x.PropertyType == typeof(TPropertyValue));
Finder = ValueGetter.CreateGetter<TTargetObject, TTargetValue>(propertyInfos,
ValueGetter.CreateGetterCase<TTargetObject, TTargetValue>);
}
public static Func<TTargetObject, TTargetValue> GetGetter(PropertyInfo info)
{
return Finder.Invoke(info);
}
}
public static class ValueGetter<TTargetObject>
{
private static readonly Func<PropertyInfo, Func<TTargetObject, object>> Finder;
static ValueGetter()
{
var propertyInfos = typeof(TTargetObject).GetRuntimeProperties()
.Where(x => x.CanRead);
Finder = ValueGetter.CreateGetter<TTargetObject, object>(propertyInfos,
ValueGetter.CreateGetterCase<TTargetObject, object>);
}
public static Func<TTargetObject, object> GetGetter(PropertyInfo info)
{
return Finder.Invoke(info);
}
}
public static class ValueSetter
{
public static object Get(Type objType, Type valueType, PropertyInfo info)
{
var bodyExp = Expression.Call(
typeof(ValueSetter<,,>).MakeGenericType(objType, info.PropertyType, valueType),
nameof(ValueSetter<object, object, object>.GetSetter),
Array.Empty<Type>(),
Expression.Constant(info));
var finalExp = Expression.Lambda<Func<object>>(bodyExp);
var func = finalExp.Compile();
var re = func.Invoke();
return re;
}
public static object Get(Type objType, PropertyInfo info)
{
var bodyExp = Expression.Call(typeof(ValueSetter<>).MakeGenericType(objType),
nameof(ValueSetter<object, object, object>.GetSetter),
Array.Empty<Type>(),
Expression.Constant(info));
var finalExp = Expression.Lambda<Func<object>>(bodyExp);
var func = finalExp.Compile();
var re = func.Invoke();
return re;
}
internal static SwitchCase CreateSetterCase<TTargetObject, TTargetValue>(PropertyInfo propertyInfo)
{
var sourceObjExp = Expression.Parameter(typeof(TTargetObject), "sourceObj");
var valueExp = Expression.Parameter(typeof(TTargetValue), "value");
var newValueExp = Expression.Convert(valueExp, propertyInfo.PropertyType);
var bodyExp = Expression.Assign(Expression.Property(sourceObjExp, propertyInfo), newValueExp);
var finalExp =
Expression.Lambda<Action<TTargetObject, TTargetValue>>(bodyExp, sourceObjExp, valueExp);
var getter = finalExp.Compile();
var caseExp = Expression.Constant(propertyInfo);
return Expression.SwitchCase(Expression.Constant(getter), caseExp);
}
internal static Func<PropertyInfo, Action<TTargetObject, TTargetValue>> CreateSetter<TTargetObject,
TTargetValue>(
IEnumerable<PropertyInfo> propertyInfos,
Func<PropertyInfo, SwitchCase> caseFactory)
{
var pExp = Expression.Parameter(typeof(PropertyInfo), "info");
var cases = propertyInfos.Select(caseFactory);
var switchExp =
Expression.Switch(pExp,
Expression.Constant(null,
typeof(Action<TTargetObject, TTargetValue>)),
null,
cases);
var funcExp = Expression.Lambda<Func<PropertyInfo, Action<TTargetObject, TTargetValue>>>(switchExp, pExp);
var re = funcExp.Compile();
return re;
}
}
public static class ValueSetter<TTargetObject, TPropertyValue, TTargetValue>
{
private static readonly Func<PropertyInfo, Action<TTargetObject, TTargetValue>> Finder;
static ValueSetter()
{
var propertyInfos = typeof(TTargetObject).GetRuntimeProperties()
.Where(x => x.CanWrite)
.Where(x => x.PropertyType == typeof(TPropertyValue));
Finder = ValueSetter.CreateSetter<TTargetObject, TTargetValue>(propertyInfos,
ValueSetter.CreateSetterCase<TTargetObject, TTargetValue>);
}
public static Action<TTargetObject, TTargetValue> GetSetter(PropertyInfo info)
{
return Finder.Invoke(info);
}
}
public static class ValueSetter<TTargetObject>
{
private static readonly Func<PropertyInfo, Action<TTargetObject, object>> Finder;
static ValueSetter()
{
var propertyInfos = typeof(TTargetObject).GetRuntimeProperties()
.Where(x => x.CanWrite);
Finder = ValueSetter.CreateSetter<TTargetObject, object>(propertyInfos,
ValueSetter.CreateSetterCase<TTargetObject, object>);
}
public static Action<TTargetObject, object> GetSetter(PropertyInfo info)
{
return Finder.Invoke(info);
}
}
public class Cl
{
public string Name { get; set; }
public string Test1 { get; set; }
public DateTime Now { get; set; }
public int Age { get; set; }
public bool Sex { get; set; }
public double Animo { get; set; }
}
static void Main(string[] args)
{
//ConstantExpression _constExp = Expression.Constant("aaa", typeof(string));//一个常量
//MethodCallExpression _methodCallexp = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), _constExp);
//Expression<Action> consoleLambdaExp = Expression.Lambda<Action>(_methodCallexp);
//consoleLambdaExp.Compile()();
var cl = new Cl();
var _nameProperty = typeof(Cl).GetProperty(nameof(Cl.Name))!;
var _ageProperty = typeof(Cl).GetProperty(nameof(Cl.Age))!;
var _nameFunc = ValueSetter<Cl, string, string>.GetSetter(_nameProperty);
ValueSetter<Cl, int, int>.GetSetter(_ageProperty).Invoke(cl, 16);
ValueSetter<Cl>.GetSetter(_nameProperty).Invoke(cl, "dalao");
cl.Name = "dalao";
cl.Age = 16;
_nameProperty.SetValue(cl, "dalao1");
_ageProperty.SetValue(cl, 17);
ValueSetter<Cl, string, string>.GetSetter(_nameProperty).Invoke(cl, "dalao2");
ValueSetter<Cl, int, int>.GetSetter(_ageProperty).Invoke(cl, 18);
ValueSetter<Cl>.GetSetter(_nameProperty).Invoke(cl, "dalao3");
_nameFunc.Invoke(cl, "dalao4");
var t1 = ValueGetter<Cl, int, int>.GetGetter(_ageProperty).Invoke(cl);
var t2 = ValueGetter<Cl, string, string>.GetGetter(_nameProperty).Invoke(cl);
var name = (string)_nameProperty.GetValue(cl);
var age = (int)_ageProperty.GetValue(cl);
}