// Subject: Complex object with set of properties and inner objectss // Mission: Describe fluent DSL to define scheme and delegate action execution // using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Text.RegularExpressions; namespace ConsoleApplication1 { internal class Program { // Scheme: public class Group { public string Name; } private class User { public string Profile { get; set; } public Group Group; } // DSL: public class Cascade<T> where T:class ,new () { private T Entity; protected List<Func<object>> References = new List<Func<object>>(); public Cascade(T entity) { Entity = entity; } public Cascade(T entity, List<Func< object>> references) { Entity = entity; References = references; } public Cascade<T> Reference(Expression<Func<T, object>> expression) { RegisterReference(expression); return this; } public Cascade<TEntity> Depended<TEntity>(Expression<Func<T, TEntity>> expression) where TEntity : class, new() { TEntity depended = RegisterReference(expression)(Entity); return new Cascade<TEntity>(depended, References); } public void Execute(string action) { foreach (Func<object> reference in References) { var value = reference(); Console.WriteLine("Executed {0} for {1}",action, value); } } public Func<T, TResult> RegisterReference<TResult>(Expression<Func<T, TResult>> expression) where TResult : class, new () { Func<T, TResult> func = expression.Compile(); References.Add(() => func(Entity) ); Debug("Registered", expression); return func; } // Action delegate: private static void Debug<TResult>(string action, Expression<Func<T, TResult>> expression) { Console.WriteLine("{0} {1}", action, MemberExpressionName(expression)); } private static string MemberExpressionName<TResult>(Expression<Func<T, TResult>> expression) { MemberExpression memberExpression = expression.Body as MemberExpression; return memberExpression.Member.Name; } } // Usage: private static void Main(string[] args) { User user = new User(); user.Profile = "admin"; user.Group = new Group(); user.Group.Name = "users"; Cascade<User> userCascade = new Cascade<User>(user); userCascade .Reference(u => u.Profile) .Depended(u => u.Group) .Reference(group => group.Name); userCascade.Execute("delete"); Console.ReadLine(); return; } } }