Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public static class DynamicExtensions
- {
- #region Fields
- private static readonly Regex methodMatcher = new Regex(@"^Find(All)?By(\w*)$", RegexOptions.Singleline | RegexOptions.Compiled);
- #endregion
- #region Public Methods
- public static dynamic AsDynamic<T>(this IEnumerable<T> source)
- {
- return new DynamicEnumerable<T>(source);
- }
- public static dynamic AsDynamic<T>(this IQueryable<T> source)
- {
- return new DynamicQueryable<T>(source);
- }
- #endregion
- #region Private Methods
- private static Expression<Func<T, bool>> BuildExpression<T>(string[] properties, object[] args)
- {
- if (properties.Length < 1)
- throw new InvalidOperationException("Need to specify at least one property.");
- if (args.Length != properties.Length)
- throw new InvalidOperationException("Method expects " + properties.Length + " parameters and only got " + args.Length + " values.");
- var param = Expression.Parameter(typeof(T), "p");
- var body = Expression.Equal(Expression.Property(param, properties[0]), Expression.Constant(args[0]));
- for (var i = 1; i < properties.Length; i++)
- body = Expression.AndAlso(body, Expression.Equal(Expression.Property(param, properties[i]), Expression.Constant(args[i])));
- return Expression.Lambda<Func<T, bool>>(body, param);
- }
- #endregion
- #region Nested Types
- private sealed class DynamicEnumerable<T> : DynamicObject
- {
- #region Fields
- private readonly IEnumerable<T> source;
- #endregion
- #region Constructors
- public DynamicEnumerable(IEnumerable<T> source)
- {
- this.source = source;
- }
- #endregion
- #region Public Methods
- public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
- {
- var match = methodMatcher.Match(binder.Name);
- if (match.Success)
- {
- var properties = match.Groups[2].Value.Split(new[] { "And" }, StringSplitOptions.RemoveEmptyEntries);
- var predicate = BuildExpression<T>(properties, args).Compile();
- if (match.Groups[1].Success)
- result = source.Where(predicate);
- else
- result = source.FirstOrDefault(predicate);
- return true;
- }
- return base.TryInvokeMember(binder, args, out result);
- }
- #endregion
- }
- private sealed class DynamicQueryable<T> : DynamicObject
- {
- #region Fields
- private readonly IQueryable<T> source;
- #endregion
- #region Constructors
- public DynamicQueryable(IQueryable<T> source)
- {
- this.source = source;
- }
- #endregion
- #region Public Methods
- public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
- {
- var match = methodMatcher.Match(binder.Name);
- if (match.Success)
- {
- var properties = match.Groups[2].Value.Split(new[] { "And" }, StringSplitOptions.RemoveEmptyEntries);
- var predicate = BuildExpression<T>(properties, args);
- if (match.Groups[1].Success)
- result = source.Where(predicate);
- else
- result = source.FirstOrDefault(predicate);
- return true;
- }
- return base.TryInvokeMember(binder, args, out result);
- }
- #endregion
- }
- #endregion
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement