我需要将一个对象的一些属性复制到另一个对象。但是,某些属性需要从decimal到int的类型转换。
我发现这个问题非常有用: Copy values from one object to another
但是,我无法弄清楚如何修改Jon Skeet和Marc Gravell的MiscUtil中的代码以检查属性类型,如果源是十进制且目标是int,则调用Convert.ToIn32()。
以下是MiscUtil的代码,我想弄清楚如何修改:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace MiscUtil.Reflection
{
/// <summary>
/// Generic class which copies to its target type from a source
/// type specified in the Copy method. The types are specified
/// separately to take advantage of type inference on generic
/// method arguments.
/// </summary>
public static class PropertyCopy<TTarget> where TTarget : class, new()
{
/// <summary>
/// Copies all readable properties from the source to a new instance
/// of TTarget.
/// </summary>
public static TTarget CopyFrom<TSource>(TSource source) where TSource : class
{
return PropertyCopier<TSource>.Copy(source);
}
/// <summary>
/// Static class to efficiently store the compiled delegate which can
/// do the copying. We need a bit of work to ensure that exceptions are
/// appropriately propagated, as the exception is generated at type initialization
/// time, but we wish it to be thrown as an ArgumentException.
/// </summary>
private static class PropertyCopier<TSource> where TSource : class
{
private static readonly Func<TSource, TTarget> copier;
private static readonly Exception initializationException;
internal static TTarget Copy(TSource source)
{
if (initializationException != null)
{
throw initializationException;
}
if (source == null)
{
throw new ArgumentNullException("source");
}
return copier(source);
}
static PropertyCopier()
{
try
{
copier = BuildCopier();
initializationException = null;
}
catch (Exception e)
{
copier = null;
initializationException = e;
}
}
private static Func<TSource, TTarget> BuildCopier()
{
ParameterExpression sourceParameter = Expression.Parameter(typeof(TSource), "source");
var bindings = new List<MemberBinding>();
foreach (PropertyInfo sourceProperty in typeof(TSource).GetProperties())
{
if (!sourceProperty.CanRead)
{
continue;
}
PropertyInfo targetProperty = typeof(TTarget).GetProperty(sourceProperty.Name);
if (targetProperty == null)
{
throw new ArgumentException("Property " + sourceProperty.Name + " is not present and accessible in " + typeof(TTarget).FullName);
}
if (!targetProperty.CanWrite)
{
throw new ArgumentException("Property " + sourceProperty.Name + " is not writable in " + typeof(TTarget).FullName);
}
if (!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
{
throw new ArgumentException("Property " + sourceProperty.Name + " has an incompatible type in " + typeof(TTarget).FullName);
}
bindings.Add(Expression.Bind(targetProperty, Expression.Property(sourceParameter, sourceProperty)));
}
Expression initializer = Expression.MemberInit(Expression.New(typeof(TTarget)), bindings);
return Expression.Lambda<Func<TSource,TTarget>>(initializer, sourceParameter).Compile();
}
}
}
}
答案 0 :(得分:4)
如果你有
public class Foo
{
public decimal Value { get; set; }
}
public class Bar
{
public int Value { get; set; }
}
然后使用AutoMapper(可从NuGet获得),您可以将对象Foo映射到对象Bar,如下所示:
Mapper.CreateMap<Foo, Bar>();
Foo foo = new Foo() { Value = 10.5M };
var bar = Mapper.Map<Bar>(foo);
// bar.Value = 10;
答案 1 :(得分:1)
我们可以使用System.Reflection。 遵循这个功能:
public static T CloneData<T>(object source)
{
var target = (T)Activator.CreateInstance(typeof(T));
Type objTypeBase = source.GetType();
Type objTypeTarget = target.GetType();
PropertyInfo _propinfo = null;
var propInfos = objTypeBase.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var propInfo in propInfos)
{
try
{
_propinfo = objTypeTarget.GetProperty(propInfo.Name, BindingFlags.Instance | BindingFlags.Public);
if (_propinfo != null)
{
_propinfo.SetValue(target, propInfo.GetValue(source));
}
}
catch (ArgumentException aex) { if (!string.IsNullOrEmpty(aex.Message)) continue; }
catch (Exception ex) { if (!string.IsNullOrEmpty(ex.Message)) return default(T); }
}
return target;
}
假设我们有两个类:
public class A
{
public string Prop1 {get ; set; }
public string Prop2 {get ; set; }
public string Prop3 {get ; set; }
public string Prop4 {get ; set; }
}
public class B
{
public string Prop2 {get ; set; }
public string Prop3 {get ; set; }
}
我们写道:
var a = new A
{
Prop1 = "A",
Prop2 = "B",
Prop3 = "C",
Prop4 = "D",
};
var b = CloneData<B>(a);
我们将获得一个B类实例,其中Prop1和Prop3值是从A。
复制的答案 2 :(得分:0)
您可以查看类似
的类型 int x = 4;
if(x.GetType()== typeof(int))
{
///DO Stuff
}
if(x.GetType()==typeof(decimal)
{
///Do stuff
}