daily pastebin goal
21%
SHARE
TWEET

Untitled

a guest Jun 19th, 2010 335 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.     public static class DynamicExtensions
  2.     {
  3.         #region Fields
  4.  
  5.         private static readonly Regex methodMatcher = new Regex(@"^Find(All)?By(\w*)$", RegexOptions.Singleline | RegexOptions.Compiled);
  6.  
  7.         #endregion
  8.  
  9.         #region Public Methods
  10.  
  11.         public static dynamic AsDynamic<T>(this IEnumerable<T> source)
  12.         {
  13.             return new DynamicEnumerable<T>(source);
  14.         }
  15.  
  16.         public static dynamic AsDynamic<T>(this IQueryable<T> source)
  17.         {
  18.             return new DynamicQueryable<T>(source);
  19.         }
  20.  
  21.         #endregion
  22.  
  23.         #region Private Methods
  24.  
  25.         private static Expression<Func<T, bool>> BuildExpression<T>(string[] properties, object[] args)
  26.         {
  27.             if (properties.Length < 1)
  28.                 throw new InvalidOperationException("Need to specify at least one property.");
  29.             if (args.Length != properties.Length)
  30.                 throw new InvalidOperationException("Method expects " + properties.Length + " parameters and only got " + args.Length + " values.");
  31.  
  32.             var param = Expression.Parameter(typeof(T), "p");
  33.             var body = Expression.Equal(Expression.Property(param, properties[0]), Expression.Constant(args[0]));
  34.             for (var i = 1; i < properties.Length; i++)
  35.                 body = Expression.AndAlso(body, Expression.Equal(Expression.Property(param, properties[i]), Expression.Constant(args[i])));
  36.             return Expression.Lambda<Func<T, bool>>(body, param);
  37.         }
  38.  
  39.         #endregion
  40.  
  41.         #region Nested Types
  42.  
  43.         private sealed class DynamicEnumerable<T> : DynamicObject
  44.         {
  45.             #region Fields
  46.  
  47.             private readonly IEnumerable<T> source;
  48.  
  49.             #endregion
  50.  
  51.             #region Constructors
  52.  
  53.             public DynamicEnumerable(IEnumerable<T> source)
  54.             {
  55.                 this.source = source;
  56.             }
  57.  
  58.             #endregion
  59.  
  60.             #region Public Methods
  61.  
  62.             public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  63.             {
  64.                 var match = methodMatcher.Match(binder.Name);
  65.                 if (match.Success)
  66.                 {
  67.                     var properties = match.Groups[2].Value.Split(new[] { "And" }, StringSplitOptions.RemoveEmptyEntries);
  68.                     var predicate = BuildExpression<T>(properties, args).Compile();
  69.  
  70.                     if (match.Groups[1].Success)
  71.                         result = source.Where(predicate);
  72.                     else
  73.                         result = source.FirstOrDefault(predicate);
  74.  
  75.                     return true;
  76.                 }
  77.                 return base.TryInvokeMember(binder, args, out result);
  78.             }
  79.  
  80.             #endregion
  81.         }
  82.  
  83.         private sealed class DynamicQueryable<T> : DynamicObject
  84.         {
  85.             #region Fields
  86.  
  87.             private readonly IQueryable<T> source;
  88.  
  89.             #endregion
  90.  
  91.             #region Constructors
  92.  
  93.             public DynamicQueryable(IQueryable<T> source)
  94.             {
  95.                 this.source = source;
  96.             }
  97.  
  98.             #endregion
  99.  
  100.             #region Public Methods
  101.  
  102.             public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  103.             {
  104.                 var match = methodMatcher.Match(binder.Name);
  105.                 if (match.Success)
  106.                 {
  107.                     var properties = match.Groups[2].Value.Split(new[] { "And" }, StringSplitOptions.RemoveEmptyEntries);
  108.                     var predicate = BuildExpression<T>(properties, args);
  109.  
  110.                     if (match.Groups[1].Success)
  111.                         result = source.Where(predicate);
  112.                     else
  113.                         result = source.FirstOrDefault(predicate);
  114.  
  115.                     return true;
  116.                 }
  117.                 return base.TryInvokeMember(binder, args, out result);
  118.             }
  119.  
  120.             #endregion
  121.         }
  122.  
  123.         #endregion
  124.     }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand