code_junkie

Refactor To Eliminate Repetition In Lamba Expression

Nov 11th, 2011
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.99 KB | None | 0 0
  1. public static Expression<Func<Foo, FooEditDto>> EditDtoSelector()
  2. {
  3. return f => new FooEditDto
  4. {
  5. PropertyA = f.PropertyA,
  6. PropertyB = f.PropertyB,
  7. PropertyC = f.PropertyC,
  8. PropertyD = f.PropertyD,
  9. PropertyE = f.PropertyE
  10. };
  11. }
  12.  
  13. public static Expression<Func<Foo, FooListDto>> ListDtoSelector()
  14. {
  15. return f => new FooDto
  16. {
  17. PropertyA = f.PropertyA,
  18. PropertyB = f.PropertyB,
  19. PropertyC = f.PropertyC
  20. };
  21. }
  22.  
  23. class FooDto
  24. { public FooDto(Bar a, Bar b, Bar c)
  25. { PropertyA = a;
  26. PropertyB = b;
  27. PropertyC = c;
  28. }
  29. public Bar PropertyA {get;set;}
  30. public Bar PropertyB {get;set;}
  31. public Bar PropertyC {get;set;}
  32. }
  33.  
  34. class FooEditDto : FooDto
  35. { public FooEditDto(Bar a, Bar b, Bar c) : base(a,b,c)
  36. public Bar PropertyD {get;set;}
  37. public Bar PropertyE {get;set;}
  38. }
  39.  
  40. public static Expression<Func<Foo, FooEditDto>> EditDtoSelector()
  41. {
  42. return f => new FooEditDto(f.PropertyA,f.PropertyB,f.PropertyC)
  43. {
  44. PropertyD = f.PropertyD,
  45. PropertyE = f.PropertyE
  46. };
  47. }
  48.  
  49. public static Expression<Func<Foo, FooEditDto>> EditDtoSelector()
  50. {
  51. return f => MagicCopier<FooEditDto>.Copy(new {
  52. f.PropertyA, f.PropertyB, f.PropertyC, f.PropertyD, f.PropertyC
  53. });
  54. }
  55.  
  56. /// <summary>
  57. /// Generic class which copies to its target type from a source
  58. /// type specified in the Copy method. The types are specified
  59. /// separately to take advantage of type inference on generic
  60. /// method arguments.
  61. /// </summary>
  62. public static class PropertyCopy<TTarget> where TTarget : class, new()
  63. {
  64. /// <summary>
  65. /// Copies all readable properties from the source to a new instance
  66. /// of TTarget.
  67. /// </summary>
  68. public static TTarget CopyFrom<TSource>(TSource source) where TSource : class
  69. {
  70. return PropertyCopier<TSource>.Copy(source);
  71. }
  72.  
  73. /// <summary>
  74. /// Static class to efficiently store the compiled delegate which can
  75. /// do the copying. We need a bit of work to ensure that exceptions are
  76. /// appropriately propagated, as the exception is generated at type initialization
  77. /// time, but we wish it to be thrown as an ArgumentException.
  78. /// </summary>
  79. private static class PropertyCopier<TSource> where TSource : class
  80. {
  81. private static readonly Func<TSource, TTarget> copier;
  82. private static readonly Exception initializationException;
  83.  
  84. internal static TTarget Copy(TSource source)
  85. {
  86. if (initializationException != null)
  87. {
  88. throw initializationException;
  89. }
  90. if (source == null)
  91. {
  92. throw new ArgumentNullException("source");
  93. }
  94. return copier(source);
  95. }
  96.  
  97. static PropertyCopier()
  98. {
  99. try
  100. {
  101. copier = BuildCopier();
  102. initializationException = null;
  103. }
  104. catch (Exception e)
  105. {
  106. copier = null;
  107. initializationException = e;
  108. }
  109. }
  110.  
  111. private static Func<TSource, TTarget> BuildCopier()
  112. {
  113. ParameterExpression sourceParameter = Expression.Parameter(typeof(TSource), "source");
  114. var bindings = new List<MemberBinding>();
  115. foreach (PropertyInfo sourceProperty in typeof(TSource).GetProperties())
  116. {
  117. if (!sourceProperty.CanRead)
  118. {
  119. continue;
  120. }
  121. PropertyInfo targetProperty = typeof(TTarget).GetProperty(sourceProperty.Name);
  122. if (targetProperty == null)
  123. {
  124. throw new ArgumentException("Property " + sourceProperty.Name
  125. + " is not present and accessible in " + typeof(TTarget).FullName);
  126. }
  127. if (!targetProperty.CanWrite)
  128. {
  129. throw new ArgumentException("Property " + sourceProperty.Name
  130. + " is not writable in " + typeof(TTarget).FullName);
  131. }
  132. if (!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
  133. {
  134. throw new ArgumentException("Property " + sourceProperty.Name
  135. + " has an incompatible type in " + typeof(TTarget).FullName);
  136. }
  137. bindings.Add(Expression.Bind(targetProperty, Expression.Property(sourceParameter, sourceProperty)));
  138. }
  139. Expression initializer = Expression.MemberInit(Expression.New(typeof(TTarget)), bindings);
  140. return Expression.Lambda<Func<TSource,TTarget>>(initializer, sourceParameter).Compile();
  141. }
  142. }
  143.  
  144. TargetType target = PropertyCopy<TargetType>.CopyFrom(new { First="Foo", Second="Bar" });
  145.  
  146. public static Expression<Func<Foo,T>>
  147. GetSelector<T>(Expression<Func<Foo,T>> f)
  148. { return f;
  149. }
  150.  
  151. /* ... */
  152. var expr = GetSelector(f => new{f.PropertyA,f.PropertyB,f.PropertyC});
Add Comment
Please, Sign In to add comment