使用C#中的泛型将用户定义的类型转换为另一个用户定义的类型

时间:2018-10-24 06:58:17

标签: c# .net .net-standard-2.0

我正在尝试使用Mapper类将一个类转换为另一个类,当涉及到用户定义类型时,它适用于非用户定义类型,它显示了异常。

  

未处理的异常:System.ArgumentException:类型'DataModal.TblBook'的对象不能转换为类型'DomainModal.Book'。      在System.RuntimeType.TryChangeType处(对象值,活页夹活页夹,CultureInfo文化,布尔布尔NeedSpecialCast)      在System.Reflection.MethodBase.CheckArguments(Object []参数,Binder活页夹,BindingFlags invokeAttr,CultureInfo文化,签名sig)      在System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck处(对象obj,BindingFlags invokeAttr,活页夹活页夹,Object []参数,CultureInfo文化)

我在运行时使用此答案How do I use reflection to call a generic method?尝试了Creating a new Generic Method

TblStudent.cs中,类型是TblBook;在Student.cs中,类型是Book我无法转换它。

但是我无法转换它。

这是我的Mapper.cs

using DomainModal;
using DataModal;
using System.Linq;
using System;
using System.Reflection;

namespace DataAccessLogic
{
    public class Mapper<T, U> where U : new()
    {
        public U Convert(T input)
        {
            U newCastType = new U();
            var fromObjectProperties = input.GetType().GetProperties();
            var toObjectProperties = newCastType.GetType().GetProperties();

            foreach (var parentProperty in fromObjectProperties)
            {

                foreach (var childProperty in toObjectProperties)
                {
                    if (parentProperty.Name == childProperty.Name)
                    {
                        childProperty.SetValue(newCastType, parentProperty.GetValue(input));
                    }
                }
            }
            /*var fromObjectProperties = input.GetType().GetProperties();
            foreach (var parentProperty in fromObjectProperties)
            {

            }*/
            return newCastType;

        }

    }
}

TblStudent.cs

using System;

namespace DataModal
{
    public class TblStudent
    {

        public string EmailId { get; set; }
        public string Password { get; set; }
        public string StudentName { get; set; }
        public string StudentId { get; set; }
        public string PhoneNumber { get; set; }
        public TblBook GetBook { get; set; }

    }
}

Student.cs

using System;

namespace DomainModal
{
    public class Student
    {

        public string EmailId { get; set; }
        public string Password { get; set; }
        public string StudentName { get; set; }
        public string StudentId { get; set; }
        public string PhoneNumber { get; set; }
        public Book GetBook { get; set; }

    }
}

此处是完整的源代码:https://gitlab.com/chintuyadavsara/console-application

我不知道我在哪里做错了。任何帮助将不胜感激

谢谢。

2 个答案:

答案 0 :(得分:2)

通过使用反射对不具有相同Type(但具有相同名称)的属性进行递归调用泛型方法的示例:

public class Mapper
{
    public static TRes Convert<TIn, TRes>(TIn obj)
    {
        TRes targetInstance = Activator.CreateInstance<TRes>();
        var sourceTypePropertyInfos = obj.GetType().GetProperties();
        var targetTypePropertyInfos = targetInstance.GetType().GetProperties();

        foreach (var sourceTypePropertyInfo in sourceTypePropertyInfos)
        {
            foreach (var targetTypePropertyInfo in targetTypePropertyInfos)
            {
                if (sourceTypePropertyInfo.Name == targetTypePropertyInfo.Name)
                {
                    if (sourceTypePropertyInfo.PropertyType == targetTypePropertyInfo.PropertyType)
                    {
                        targetTypePropertyInfo.SetValue(targetInstance, sourceTypePropertyInfo.GetValue(obj));
                    }
                    else
                    {
                        var sourcePropertyValue = sourceTypePropertyInfo.GetValue(obj);
                        var methodInfo = typeof(Mapper).GetMethod(nameof(Mapper.Convert));
                        var genericMethodInfo = methodInfo.MakeGenericMethod(sourceTypePropertyInfo.PropertyType, targetTypePropertyInfo.PropertyType);
                        var targetValue = genericMethodInfo.Invoke(new Mapper(), new[] { sourcePropertyValue });
                        targetTypePropertyInfo.SetValue(targetInstance, targetValue);
                    }
                }
            }
        }
        return targetInstance;
    }
}

称呼为:

var student = Mapper.Convert<TblStudent, Student>(tblStudent);

答案 1 :(得分:1)

您可以执行以下操作。

public class Mapper<T, U> where U : new()
    {
        public U Convert(T input)
        {
            U newCastType = new U();
            var fromObjectProperties = input.GetType().GetProperties();
            var toObjectProperties = newCastType.GetType().GetProperties();

            foreach (var parentProperty in fromObjectProperties)
            {

                foreach (var childProperty in toObjectProperties)
                {

                    if((parentProperty.Name == childProperty.Name) && parentProperty.PropertyType.IsClass && parentProperty.PropertyType.Name != "String")
                    {

                        var typeInfo = typeof(Mapper<,>);
                        var genericType = typeInfo.MakeGenericType(parentProperty.PropertyType, childProperty.PropertyType);

                        var genericMethodInfo = genericType.GetMethod("Convert");
                        var ojb = Activator.CreateInstance(genericType);
                        var targetValue = genericMethodInfo.Invoke(ojb, new[] { parentProperty.GetValue(input) });
                        childProperty.SetValue(newCastType, targetValue);
                    }
                    else if ((parentProperty.Name == childProperty.Name))
                    {
                        childProperty.SetValue(newCastType, parentProperty.GetValue(input));
                    }
                }
            }
            /*var fromObjectProperties = input.GetType().GetProperties();
            foreach (var parentProperty in fromObjectProperties)
            {

            }*/
            return newCastType;

        }

    }