在 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;
}
}
我正在尝试使用 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;
}
}