//---------------------------------------------------------------------
// This file is part of the Background Motion solution.
//
// Copyright (C) Mindscape (TM). All rights reserved.
// http://www.mindscape.co.nz
//
// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Mindscape.BackgroundMotion.Core.Utilities
{
/// <summary>
/// Provides a simple reflection based mapper to perform a Data Mapping between two types of objects
/// </summary>
/// <remarks>
/// We are working on the convention that the source object will be property based and the target will be field based
/// This is used between our domain entities and DTO's
/// </remarks>
/// <typeparam name="T"></typeparam>
public class DataMapper<T> where T : new()
{
// TODO: Not thread-safe - using ThreadStatic should be ok here
private static Dictionary<Type, Dictionary<string, PropertyInfo>> _propertyReflectionCache =
new Dictionary<Type, Dictionary<string, PropertyInfo>>();
private static Dictionary<Type, FieldInfo[]> _fieldReflectionCache = new Dictionary<Type, FieldInfo[]>();
/// <summary>
/// Use a reflection based mapping to map between properties and fields
/// </summary>
public static T Map(object source)
{
T target = new T();
FieldInfo[] fields = GetFieldSetInfo(typeof(T));
if (source == null)
{
return target;
}
foreach (FieldInfo field in fields)
{
try
{
PropertyInfo sourceProperty = GetPropertyInfo(source.GetType(), field.Name);
if (sourceProperty == null)
{
continue;
}
field.SetValue(target, sourceProperty.GetValue(source, null));
}
catch (InvalidCastException)
{
}
}
return target;
}
/// <summary>
/// Finds a property in the reflection cache
/// </summary>
private static PropertyInfo GetPropertyInfo(Type t, string name)
{
if (_propertyReflectionCache.ContainsKey(t))
{
if (_propertyReflectionCache[t].ContainsKey(name))
{
return _propertyReflectionCache[t][name];
}
_propertyReflectionCache[t].Add(name, t.GetProperty(name, BindingFlags.Public | BindingFlags.Instance));
return _propertyReflectionCache[t][name];
}
Dictionary<string, PropertyInfo> dictionary = new Dictionary<string, PropertyInfo>();
_propertyReflectionCache.Add(t, dictionary);
dictionary.Add(name, t.GetProperty(name, BindingFlags.Public | BindingFlags.Instance));
return _propertyReflectionCache[t][name];
}
/// <summary>
/// Finds a collection of field information from the reflection cache
/// </summary>
private static FieldInfo[] GetFieldSetInfo(Type t)
{
if (_fieldReflectionCache.ContainsKey(t))
{
return _fieldReflectionCache[t];
}
_fieldReflectionCache.Add(t, t.GetFields(BindingFlags.Public | BindingFlags.Instance));
return _fieldReflectionCache[t];
}
}
}
|