Click here to Skip to main content
15,886,724 members
Articles / Web Development / ASP.NET

Signum Framework Principles

Rate me:
Please Sign up or sign in to vote.
4.74/5 (27 votes)
25 Jul 2011CPOL18 min read 98.9K   1.1K   86  
Explains the philosophy behind Signum Framework, an ORM with a full LINQ Provider that encourages an entities-first approach.
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;


namespace Signum.Utilities.ExpressionTrees
{
	public static class GeneralUtils
	{
		/// <summary>
		/// Returns whether string contains any of the specified keywords as a substring.
		/// </summary>
		/// <param name="value">Value of the string</param>
		/// <param name="keywords">Array with keywords</param>
		/// <returns>True when value contains any of the specified keywords</returns>
		[MethodExpander(typeof(ExpandContainsAny))]
		public static bool ContainsAny(this string value, params string[] keywords)
		{
			return keywords.Any((s) => value.Contains(s));
		}


		/// <summary>
		/// Returns whether string contains all of the specified keywords as a substring.
		/// </summary>
		/// <param name="value">Value of the string</param>
		/// <param name="keywords">Array with keywords</param>
		/// <returns>True when value contains all of the specified keywords</returns>
		[MethodExpander(typeof(ExpandContainsAll))]
		public static bool ContainsAll(this string value, params string[] keywords)
		{
			return keywords.All((s) => value.Contains(s));
		}
	}

	public static class Linq
	{
        /// <summary>
        /// Utility function for building expression trees for lambda functions
        /// that return C# anonymous type as a result (because you can't declare 
        /// it using Expression&lt;Func&lt;...&gt;&gt; syntax)
        /// </summary>
        public static Expression<Func<R>> Expr<R>(Expression<Func<R>> f)
        {
            return f;
        }

		/// <summary>
		/// Utility function for building expression trees for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using Expression&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Expression<Func<T, R>> Expr<T, R>(Expression<Func<T, R>> f)
		{
			return f;
		}

		/// <summary>
		/// Utility function for building expression trees for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using Expression&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Expression<Func<T0, T1, R>> Expr<T0, T1, R>(Expression<Func<T0, T1, R>> f)
		{
			return f;
		}

		/// <summary>
		/// Utility function for building expression trees for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using Expression&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Expression<Func<T0, T1, T2, R>> Expr<T0, T1, T2, R>(Expression<Func<T0, T1, T2, R>> f)
		{
			return f;
		}

		/// <summary>
		/// Utility function for building expression trees for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using Expression&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Expression<Func<T0, T1, T2, T3, R>> Expr<T0, T1, T2, T3, R>(Expression<Func<T0, T1, T2, T3, R>> f)
		{
			return f;
		}

		/// <summary>
		/// Utility function for building delegates for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using delegates&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Func<T, R> Func<T, R>(Func<T, R> f)
		{
			return f;
		}

		/// <summary>
		/// Utility function for building delegates for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using delegates&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Func<T0, T1, R> Func<T0, T1, R>(Func<T0, T1, R> f)
		{
			return f;
		}

		/// <summary>
		/// Utility function for building delegates for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using delegates&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Func<T0, T1, T2, R> Func<T0, T1, T2, R>(Func<T0, T1, T2, R> f)
		{
			return f;
		}

		/// <summary>
		/// Utility function for building delegates for lambda functions
		/// that return C# anonymous type as a result (because you can't declare 
		/// it using delegates&lt;Func&lt;...&gt;&gt; syntax)
		/// </summary>
		public static Func<T0, T1, T2, T3, R> Func<T0, T1, T2, T3, R>(Func<T0, T1, T2, T3, R> f)
		{
			return f;
		}
	}

	#region MethodExpanders

	abstract class StringArrayExpanderBase : IMethodExpander
	{
		protected MethodInfo contMeth;
		protected Expression selfRef;
		protected abstract string MethodName { get; }
		protected abstract Func<Expression, string, Expression> Agg { get; }

		public Expression Expand(Expression selfRef, IEnumerable<Expression> parameters)
		{
			this.selfRef = selfRef;
			string[] vals;
			try
			{
				vals = (string[])ExpressionExpander.Evaluate(parameters.First());
				if (vals.Length == 0) throw new Exception();
			}
			catch
			{
				throw new ArgumentException(string.Format("First argument for the '{0}' method must be non empty string array!", MethodName));
			}

			// Init parameters
			contMeth = typeof(string).GetMethod("Contains");

			// Combine using And when method is ContainsAll or using Or when method is ConainsAny
			var init = Expression.Call(selfRef, contMeth, Expression.Constant(vals[0]));
            return vals.Skip(1).Aggregate(init, Agg);
		}
	}

	class ExpandContainsAny : StringArrayExpanderBase
	{
		protected override string MethodName
		{
			get { return "ContainsAny"; }
		}

		protected override Func<Expression, string, Expression> Agg
		{
			get 
			{ 
				return ( expr, str) => Expression.Or(expr,
					Expression.Call(selfRef, contMeth, Expression.Constant(str))); 
			}
		}
	}

	class ExpandContainsAll : StringArrayExpanderBase
	{
		protected override string MethodName
		{
			get { return "ContainsAll"; }
		}

		protected override Func<Expression, string, Expression> Agg
		{
			get
			{
				return ( expr, str) => Expression.And(expr,
					Expression.Call(selfRef, contMeth, Expression.Constant(str))); 
			}
		}
	}

	#endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Signum Software
Spain Spain
I'm Computer Scientist, one of the founders of Signum Software, and the lead developer behind Signum Framework.

www.signumframework.com

I love programming in C#, Linq, Compilers, Algorithms, Functional Programming, Computer Graphics, Maths...

Comments and Discussions