我可以使用以下方法将对象转换为给定类型:
public static TTarget Convert<TTarget>(object source) where TTarget : new()
{
var target = new TTarget();
Type targetType = typeof (TTarget);
foreach (PropertyInfo sourceProperty in source.GetType().GetProperties())
{
if (!sourceProperty.CanRead || (sourceProperty.GetIndexParameters().Length > 0))
continue;
PropertyInfo targetProperty = targetType.GetProperty(sourceProperty.Name);
if ((targetProperty != null) && (targetProperty.CanWrite))
targetProperty.SetValue(target, sourceProperty.GetValue(source, null), null);
}
return target;
}
它适用于属性为值类型等的简单类,但复杂的属性需要映射到另一个类,它不是很清楚如何去做。如果我将映射存储到静态属性中:
private static Dictionary<Type, Type> Mappings;
static TypeConverter()
{
Mappings = new Dictionary<Type, Type>
{
{typeof (DbSpace), typeof (DmsSpace)},
{typeof (DbDirectory), typeof (DmsDirectory)},
{typeof (DbFile), typeof (DmsFile)}
};
}
我似乎找不到一种方法来找到利用此信息转换复杂属性的方法。 如何使用上述映射转换复杂属性?
问题的症结在于:如果我只有一个new
对象,如何调用Type
?
答案 0 :(得分:5)
Activator.CreateInstance(type)
,这里有msdn的链接,因为那些认为我的答案不够“精心”的人(获得3个downvotes for spot-on as-short-as-essential答案)..
您是否也查看了AutoMapper?
答案 1 :(得分:2)
您可以使用许多序列化程序(JavaScriptSerializer,XmlSerializer,Json.Net等) 只要符号名称匹配,就可以对对象进行“深度转换”。
举例说明var class1 = new Class1() { Property = "a", SubProperty = new SubClass1() { SubProperty = "b" } };
var class2 = Convert<Class2>(class1);
public static TTarget Convert<TTarget>(object source) where TTarget : new()
{
var ser = new JavaScriptSerializer();
var json = ser.Serialize(source);
return ser.Deserialize<TTarget>(json);
}
public class Class1
{
public string Property { get; set; }
public SubClass1 SubProperty { get; set; }
}
public class SubClass1
{
public string SubProperty { get; set; }
}
public class Class2
{
public string Property { get; set; }
public SubClass2 SubProperty { get; set; }
}
public class SubClass2
{
public string SubProperty { get; set; }
}
答案 2 :(得分:1)
使用AutoMapper而不是手动执行。
答案 3 :(得分:0)
使用Activator.CreateInstance
的解决方案:
public static class TypeConverter
{
private static Dictionary<Type, Type> Mappings;
static TypeConverter()
{
Mappings = new Dictionary<Type, Type>
{
{typeof (DbSpace), typeof (DmsSpace)},
{typeof (DbDirectory), typeof (DmsDirectory)},
{typeof (DbFile), typeof (DmsFile)}
};
}
public static object Convert(object source, Type targetType)
{
var target = Activator.CreateInstance(targetType);
foreach (PropertyInfo sourceProperty in source.GetType().GetProperties())
{
if (!sourceProperty.CanRead || (sourceProperty.GetIndexParameters().Length > 0))
continue;
PropertyInfo targetProperty = targetType.GetProperty(sourceProperty.Name);
object value = sourceProperty.GetValue(source, null);
if ((targetProperty != null) && (targetProperty.CanWrite))
{
if (value != null)
{
Type valueType = value.GetType();
Type mappedTypeKey = Mappings.Keys.FirstOrDefault(valueType.IsAssignableFrom);
if (mappedTypeKey != null)
{
targetProperty.SetValue(target, Convert(value, Mappings[mappedTypeKey]), null);
}
else
{
targetProperty.SetValue(target, value, null);
}
}
else
{
targetProperty.SetValue(target, null, null);
}
}
}
return target;
}
public static TTarget Convert<TTarget>(object source) where TTarget : class, new()
{
return Convert(source, typeof (TTarget)) as TTarget;
}
}
使用我的TypeConverter类的示例代码:
spaces = ctx.DbSpaces.Include("Root").ToList().Select(TypeConverter.Convert<DmsSpace>).ToList();
使用AutoMapper的解决方案:
Mapper.CreateMap<DbSpace, DmsSpace>();
Mapper.CreateMap<DbSpace, IDmsSpace>();
Mapper.CreateMap<DbDirectory, DmsDirectory>();
Mapper.CreateMap<DbDirectory, IDmsDirectory>();
使用AutoMapper的示例代码:
spaces = ctx.DbSpaces.Include("Root").ToList().Select(Mapper.Map<DmsSpace>).ToList();