在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转成实体类

C# new IEnumerable 怎么初始化?

C# 中yield 的用法以及性能提升

C# 字符串转成枚举正确的方法

c# 无损高质量压缩图片

C# List Sort 自定义排序方法实现