Easy way to copy object values across to an object of another type?
I have been looking to make my application a little more scalable by specifying a base data model which I intend to act as a container so that the data sent through to another application is always of the correct structure.
However I want to be able to easily load data from sources such as XML and databases in the future, so I was wondering how to go about copying the values of one object to the base data model object, where the object im copying the values from may not be of the same structure (so I mainly just want to match up property names).
Here is what I tried:
public Dictionary<string, object> ObjectValues(object source)
{
if(source == null)
return null;
Dictionary<string, object> properties = new Dictionary<string, object>();
foreach (PropertyInfo propInfo in source.GetType().GetProperties())
{
try
{
object value = propInfo.GetValue(source, null);
properties.Add(propInfo.Name, value);
if (!value.GetType().IsPrimitive && !value.GetType().IsValueType)
{
Dictionary<string, object> internalProperties = ProxyValues(value);
if (internalProperties != nu开发者_运维百科ll)
foreach (KeyValuePair<string, object> internalProp in internalProperties)
properties.Add(String.Format("{0}.{1}", propInfo.Name, internalProp.Key), internalProp.Value);
}
}
catch (TargetParameterCountException) { }
}
return properties;
}
Thanks, Alex.
If I understand your question correctly, you probably want to look at something like AutoMapper
You set up configurations:
Mapper.CreateMap<TypeA, TypeB>().ForMember(dest => dest.PropB, opt => opt.MapFrom(src => src.PropA));
Which will create a mapping from TypeA to TypeB, where the property PropA will be copied to PropB. Then when you want to use the mapping:
TypeA a = new TypeA();
TypeB b = new TypeB();
Mapper.Map(a, b);
Mapping configurations can even use custom resolvers, so if you want to do complex work when copying, you can.
There is also ValueInjecter, which some people prefer over AutoMap
Try AutoMapper. It maps disparate types that have matching property names and also has several methods that take in expressions to customize mappings
You are on the right track. What you can do is use extension methods to extend the base type object
with a merge
function. This sort of thing is relatively trivial to write yourself. Here is one i use:
/// <summary>
/// Merges the equivalent properties from the source to this object.
/// </summary>
/// <typeparam name="T">Any reference type.</typeparam>
/// <param name="destination">This object, which receives the values.</param>
/// <param name="source">The source object that the values are taken from.</param>
public static void MergeFrom<T>(this object destination, T source)
{
Type destinationType = destination.GetType();
PropertyInfo[] propertyInfos = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var propertyInfo in propertyInfos)
{
PropertyInfo destinationPropertyInfo = destinationType.GetProperty(propertyInfo.Name, BindingFlags.Public | BindingFlags.Instance);
if (destinationPropertyInfo != null)
{
if (destinationPropertyInfo.CanWrite && propertyInfo.CanRead && (destinationPropertyInfo.PropertyType == propertyInfo.PropertyType))
{
object o = propertyInfo.GetValue(source, null);
destinationPropertyInfo.SetValue(destination, o, null);
}
}
}
}
to use it is quite simple:
obj1.MergeFrom(obj2);
will merge the like properties from obj2
back into obj1
, using only equivalent property names and types. Note the lack of exception handling - this is on purpose, if it fails then i want to know about it rather than handling and swallowing exceptions.
You can also take this concept and put it directly on a Dictionary<string, object>
either as a MergeFrom
, or as a LoadFrom
, extension methods give you quite a bit of flexibility.
精彩评论