Created
April 12, 2011 18:51
-
-
Save ldhertert/916128 to your computer and use it in GitHub Desktop.
This is ugly. Never meant for anyone else to see
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Linq.Expressions; | |
using Core.Extensibility.Extensions; | |
using System.ComponentModel; | |
using System.Reflection; | |
using System.ComponentModel.DataAnnotations; | |
namespace Core.Reflection | |
{ | |
public interface IMappableObject<T> | |
{ | |
object GetValue(T srcObject); | |
void SetValue(T srcObject, object value); | |
} | |
public class PropertySpecifier<T> : IMappableObject<T> | |
{ | |
public PropertySpecifier(Expression<Func<T, object>> expression) | |
{ | |
MemberExpression _expression = null; | |
if (expression.Body is MemberExpression) | |
_expression = (expression.Body) as MemberExpression; | |
else if (expression.Body is UnaryExpression) | |
_expression = ((UnaryExpression)expression.Body).Operand as MemberExpression; | |
if (_expression == null) | |
throw new ArgumentException(); | |
this.PropertyName = _expression.Member.Name; | |
} | |
public PropertySpecifier(string propertyName) | |
{ | |
this.PropertyName = propertyName; | |
} | |
public string PropertyName { get; set; } | |
public object GetValue(T srcObject) | |
{ | |
return srcObject.GetMemberValue(this.PropertyName); | |
} | |
public void SetValue(T srcObject, object value) | |
{ | |
srcObject.SetMemberValue(this.PropertyName, value, false); | |
} | |
} | |
public class ValueSpecifier<T> : IMappableObject<T> | |
{ | |
private object Value { get; set; } | |
public ValueSpecifier(object value) | |
{ | |
this.Value = value; | |
} | |
public object GetValue(T srcObject) | |
{ | |
return this.Value; | |
} | |
public void SetValue(T srcObject, object value) | |
{ | |
throw new InvalidOperationException(); | |
} | |
} | |
public class MethodSpecifier<T> : IMappableObject<T> | |
{ | |
Func<T, object> _expression; | |
public MethodSpecifier(Func<T, object> expression) | |
{ | |
_expression = expression; | |
if (_expression == null) | |
throw new ArgumentException(); | |
} | |
public object GetValue(T srcObject) | |
{ | |
return _expression(srcObject); | |
} | |
public void SetValue(T srcObject, object value) | |
{ | |
throw new InvalidOperationException(); | |
} | |
} | |
public class PropertyMapEntry<TLeft, TRight> | |
{ | |
public IMappableObject<TLeft> Left { get; set; } | |
public IMappableObject<TRight> Right { get; set; } | |
public Func<TLeft, bool> Condition { get; set; } | |
[Obsolete("Use 'To' instead")] | |
public PropertyMapEntry<TLeft, TRight> MapsTo(Expression<Func<TRight, object>> expression) | |
{ | |
this.Right = new PropertySpecifier<TRight>(expression); | |
return this; | |
} | |
[Obsolete("Use 'To' instead")] | |
public PropertyMapEntry<TLeft, TRight> MapsTo(string propertyName) | |
{ | |
this.Right = new PropertySpecifier<TRight>(propertyName); | |
return this; | |
} | |
public PropertyMapEntry<TLeft, TRight> To(Expression<Func<TRight, object>> expression) | |
{ | |
this.Right = new PropertySpecifier<TRight>(expression); | |
return this; | |
} | |
public PropertyMapEntry<TLeft, TRight> To(string propertyName) | |
{ | |
this.Right = new PropertySpecifier<TRight>(propertyName); | |
return this; | |
} | |
public PropertyMapEntry<TLeft, TRight> Conditionally(Func<TLeft, bool> condition) | |
{ | |
this.Condition = condition; | |
return this; | |
} | |
public void MapValue(TLeft leftObject, TRight rightObejct) | |
{ | |
if (this.Condition == null || this.Condition(leftObject)) | |
{ | |
this.Right.SetValue(rightObejct, this.Left.GetValue(leftObject)); | |
} | |
} | |
public void MapValueIfReadOnly(TLeft leftObject, TRight rightObject) | |
{ | |
//checks the rightObject type and any metadata type associated with it for ReadOnly attribute on the Property. | |
//if found, it will set the value. | |
Type t = typeof(TRight); | |
PropertyInfo pi = t.GetProperty(((PropertySpecifier<TRight>)this.Right).PropertyName); | |
bool isReadOnly = ReadOnlyAttribute.IsDefined(pi, typeof(ReadOnlyAttribute)); | |
if (!isReadOnly) | |
{ | |
//check for meta data class. | |
MetadataTypeAttribute[] metaAttr = (MetadataTypeAttribute[])t.GetCustomAttributes(typeof(MetadataTypeAttribute), true); | |
if (metaAttr.Length > 0) | |
{ | |
foreach (MetadataTypeAttribute attr in metaAttr) | |
{ | |
t = attr.MetadataClassType; | |
pi = t.GetProperty(((PropertySpecifier<TRight>)this.Right).PropertyName); | |
if (pi != null) | |
isReadOnly = ReadOnlyAttribute.IsDefined(pi, typeof(ReadOnlyAttribute)); | |
if (isReadOnly) | |
break; | |
} | |
} | |
} | |
if ((this.Condition == null || this.Condition(leftObject)) && isReadOnly) | |
{ | |
this.Right.SetValue(rightObject, this.Left.GetValue(leftObject)); | |
} | |
} | |
} | |
public class PropertyMapper<TLeft, TRight> | |
{ | |
public PropertyMapper() | |
{ | |
Entries = new List<PropertyMapEntry<TLeft, TRight>>(); | |
} | |
public PropertyMapEntry<TLeft, TRight> Map(Func<TLeft, object> expression) | |
{ | |
PropertyMapEntry<TLeft, TRight> mapEntry = new PropertyMapEntry<TLeft, TRight> { Left = new MethodSpecifier<TLeft>(expression), Right = null }; | |
this.Entries.Add(mapEntry); | |
return mapEntry; | |
} | |
public PropertyMapEntry<TLeft, TRight> Map(string propertyName) | |
{ | |
PropertyMapEntry<TLeft, TRight> mapEntry = new PropertyMapEntry<TLeft, TRight> { Left = new PropertySpecifier<TLeft>(propertyName), Right = null }; | |
this.Entries.Add(mapEntry); | |
return mapEntry; | |
} | |
public PropertyMapEntry<TLeft, TRight> MapConstant(object value) | |
{ | |
PropertyMapEntry<TLeft, TRight> mapEntry = new PropertyMapEntry<TLeft, TRight> { Left = new ValueSpecifier<TLeft>(value), Right = null }; | |
this.Entries.Add(mapEntry); | |
return mapEntry; | |
} | |
public List<PropertyMapEntry<TLeft, TRight>> Entries { get; set; } | |
} | |
public class BidirectionalPropertyMapper<TLeft, TRight> | |
{ | |
public class UnmappedBiderectionalProperties | |
{ | |
public PropertyMapEntry<TLeft, TRight> UnmappedLeftToRight { get; set; } | |
public PropertyMapEntry<TRight, TLeft> UnmappedRightToLeft { get; set; } | |
public UnmappedBiderectionalProperties MapsTo(Expression<Func<TRight, object>> expression) | |
{ | |
this.UnmappedLeftToRight.Right = new PropertySpecifier<TRight>(expression); | |
this.UnmappedRightToLeft.Left = new PropertySpecifier<TRight>(expression); | |
return this; | |
} | |
public UnmappedBiderectionalProperties MapsTo(string propertyName) | |
{ | |
this.UnmappedLeftToRight.Right = new PropertySpecifier<TRight>(propertyName); | |
this.UnmappedRightToLeft.Left = new PropertySpecifier<TRight>(propertyName); | |
return this; | |
} | |
public UnmappedBiderectionalProperties ConditionallyLeftToRight(Func<TLeft, bool> condition) | |
{ | |
this.UnmappedLeftToRight.Condition = condition; | |
return this; | |
} | |
public UnmappedBiderectionalProperties ConditionallyRightToLeft(Func<TRight, bool> condition) | |
{ | |
this.UnmappedRightToLeft.Condition = condition; | |
return this; | |
} | |
} | |
public BidirectionalPropertyMapper() | |
{ | |
this.LeftToRightMapper = new PropertyMapper<TLeft, TRight>(); | |
this.RightToLeftMapper = new PropertyMapper<TRight, TLeft>(); | |
} | |
public PropertyMapper<TLeft, TRight> LeftToRightMapper { get; set; } | |
public PropertyMapper<TRight, TLeft> RightToLeftMapper { get; set; } | |
public UnmappedBiderectionalProperties OneToOneProperty(Expression<Func<TLeft, object>> leftExpression) | |
{ | |
UnmappedBiderectionalProperties unmappedProperties = new UnmappedBiderectionalProperties(); | |
unmappedProperties.UnmappedLeftToRight = new PropertyMapEntry<TLeft, TRight> { Left = new PropertySpecifier<TLeft>(leftExpression), Right = null }; | |
unmappedProperties.UnmappedRightToLeft = new PropertyMapEntry<TRight, TLeft> { Left = null, Right = new PropertySpecifier<TLeft>(leftExpression) }; | |
this.LeftToRightMapper.Entries.Add(unmappedProperties.UnmappedLeftToRight); | |
this.RightToLeftMapper.Entries.Add(unmappedProperties.UnmappedRightToLeft); | |
return unmappedProperties; | |
} | |
public UnmappedBiderectionalProperties OneToOneProperty(string propertyName) | |
{ | |
UnmappedBiderectionalProperties unmappedProperties = new UnmappedBiderectionalProperties(); | |
unmappedProperties.UnmappedLeftToRight = new PropertyMapEntry<TLeft, TRight> { Left = new PropertySpecifier<TLeft>(propertyName), Right = null }; | |
unmappedProperties.UnmappedRightToLeft = new PropertyMapEntry<TRight, TLeft> { Left = null, Right = new PropertySpecifier<TLeft>(propertyName) }; | |
this.LeftToRightMapper.Entries.Add(unmappedProperties.UnmappedLeftToRight); | |
this.RightToLeftMapper.Entries.Add(unmappedProperties.UnmappedRightToLeft); | |
return unmappedProperties; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment