Skip to content

Instantly share code, notes, and snippets.

@MMF
Last active September 7, 2023 19:47
Show Gist options
  • Save MMF/4acd8f638b42c34a25bc27756b941b0b to your computer and use it in GitHub Desktop.
Save MMF/4acd8f638b42c34a25bc27756b941b0b to your computer and use it in GitHub Desktop.
MappingExtensions For C#
using System.Linq.Expressions;
namespace Utilities.Extentions;
public static class ObjectExtensions
{
/// <summary>
/// dynamically set the value of an object's property using property name.
/// </summary>
/// <param name="obj"></param>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
public static void SetPropertyValue(this Object obj, string propertyName, string propertyValue)
{
// get property by name
var property = obj.GetType().GetProperties().FirstOrDefault(p => p.Name.Equals(propertyName, StringComparison.InvariantCultureIgnoreCase));
if (property != null)
{
// get curren property type
Type propertyType = property.PropertyType;
// if type? is nullable
Type typeOfProp = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
// get value
var convertedValue = Convert.ChangeType(propertyValue, typeOfProp);
// set value
property.SetValue(obj, convertedValue);
}
}
/// <summary>
/// Maps an object to another object.
/// Assign values of similar properties from source object to targetObject.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj">the source object</param>
/// <param name="targetObject">The target object that you are going to map to.</param>
/// <param name="ignoreList">string array of properties to be ignored </param>
/// <returns></returns>
public static T MapTo<T>(this object obj, T targetObject, string[]? ignoreList = null) where T : class
{
var sourceProperities = obj.GetType().GetProperties().ToList();
var targetProperities = targetObject.GetType().GetProperties().ToList();
foreach (var sourceProp in sourceProperities)
{
var targetProp = targetProperities.Where(t => t.Name.Equals(sourceProp.Name, StringComparison.InvariantCultureIgnoreCase) &&
sourceProp.PropertyType.Equals(t.PropertyType) &&
t.CanWrite && sourceProp.CanRead).FirstOrDefault();
if (ignoreList != null && ignoreList.Contains(sourceProp.Name))
continue;
if (targetProp != null)
targetProp.SetValue(targetObject, sourceProp.GetValue(obj));
}
return targetObject;
}
/// <summary>
/// Maps an object to a new object of another Type T
/// First it create an object from type T, then it assigns similar properities from source object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T MapTo<T>(this object obj) where T : class, new()
{
var targetObject = new T();
return obj.MapTo(targetObject);
}
/// <summary>
/// Maps an object from another object with similar properities
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="targetObj"></param>
/// <param name="sourceObj"></param>
public static void MapFrom<T>(this object targetObj, T sourceObj) where T : class
{
sourceObj.MapTo(targetObj);
}
/// <summary>
/// Maps an object to another object.
/// Assign values of similar properties from source object to targetObject.
/// Allows ignoring properities.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="targetObject"></param>
/// <param name="ignoreAction"></param>
/// <returns></returns>
public static T MapTo<T>(this object obj, T targetObject, Action<MappingOptions<T>> ignoreAction) where T : class
{
var mappingOptions = new MappingOptions<T>();
ignoreAction.Invoke(mappingOptions);
return obj.MapTo(targetObject, mappingOptions.ignoreList.ToArray());
}
}
public class MappingOptions<T>
{
public List<string> ignoreList = new();
public void Ignore(Expression<Func<T, object>> ignoreColumn)
{
string? propertyName;
if (ignoreColumn.Body is MemberExpression expression)
{
propertyName = expression.Member.Name;
}
else
{
var operand = ((UnaryExpression)ignoreColumn.Body).Operand;
propertyName = ((MemberExpression)operand).Member.Name;
}
ignoreList.Add(propertyName);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment