我正在尝试使用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
我不知道我在哪里做错了。任何帮助将不胜感激
谢谢。
答案 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;
}
}