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

Convert a User defined type to another user defined type using Generics in C#

我正在尝试使用 Mapper class 将 class 转换为另一个 class,它适用于非用户定义的类型用户定义类型,显示异常。

Unhandled Exception: System.ArgumentException: Object of type 'DataModal.TblBook' cannot be converted to type 'DomainModal.Book'. at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast) at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

我已经尝试 Creating a new Generic Method 在运行时使用这个答案 How do I use reflection to call a 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

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

谢谢。

使用反射递归调用不相同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);

你可以这样做。

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;

        }

    }