在C#中把dynamic弱类型转成强类型,如果考虑到高效那么使用Expression表达式是一个很不错的选择,如果你还不知道什么是Expression,请先自行搜索了解一下,以及它的优势在哪里。在这里推荐下这个入门文章 :https://www.cnblogs.com/Ninputer/archive/2009/09/08/expression_tree3.html 以及缅怀一下前辈留下的宝贵学习资料。
这里可以加入一点特殊处理逻辑,比如在dynamic中我收的是时间戳,那么很可能在实体中要求的是一个DateTime类型的,如果有其它转换可以参考,都是一样的思路。
public interface IConvert
{
object Convert(string timeStamp);
}
public class ConvertDateTimeAttribute : Attribute, IConvert
{
public ConvertDateTimeAttribute()
{
}
public object Convert(string timeStamp)
{
DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
long lTime = long.Parse(timeStamp + "0000000");
TimeSpan toNow = new TimeSpan(lTime);
return dtStart.Add(toNow);
}
下面代码是真正通过Expression实现映射的代码封装,其中对字符中的空值也做了处理,如果有其它要求可自行扩展。
public static T MakeInstance<T>(dynamic dynObj) where T:new()
{
T instance = new T();
Type type = instance.GetType();
PropertyInfo[] properties = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
foreach(PropertyInfo p in properties)
{
//get
MemberExpression memberExp = Expression.Property(Expression.Constant(dynObj), p.Name);
var getterExp = Expression.Lambda<Func<string>>(memberExp).Compile();
var val = getterExp();
if (val == null)
{
if (p.PropertyType == typeof(string))
{
val = string.Empty;
}
}
dynamic objVal = val;
foreach (var attr in Attribute.GetCustomAttributes(p))
{
IConvert conver = attr as IConvert;
if (conver != null)
{
objVal = conver.Convert(val);
}
}
//set
Expression instanceCast = Expression.Constant(instance, type);
MethodInfo methodInfo = p.SetMethod;
Type methodDelegateType = Expression.GetActionType(new Type[] { p.PropertyType });
ParameterExpression[] parameterExpression = new ParameterExpression[] { Expression.Parameter(p.PropertyType, p.Name) };
MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpression);
var lambdaExpression = Expression.Lambda(methodDelegateType, methodCall, parameterExpression);
var invoke = Expression.Invoke(lambdaExpression, Expression.Constant(Convert.ChangeType(objVal, p.PropertyType)));
Expression.Lambda<Action>(invoke).Compile()();
}
return instance;
}
抛砖引玉,欢迎指正,同理在Class类型转换动态赋值也是一样道理。有问题可在公众号直接留言。
推荐文章:
C# 通过Expression高效的把dynamic转成实体类