21
Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees Rasmus Kromann-Larsen

Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Embed Size (px)

Citation preview

Page 1: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Rasmus Kromann-Larsen

Page 2: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Me

• Freelance .NET Developer

• Core Group Member– Copenhagen .NET User Group– Aarhus .NET User Group

• JetBrains Academy Expert

Page 3: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Agenda

• Domain Specific Languages

• Static Reflection

• Code

Page 4: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Domain Specific Languages

• Language targeted at a specific problem

• Goals– Expressiveness / Productivity– Declarative over Imperative– Communication

• External vs Internal

Page 5: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

SELECT ID, LastNameFROM Employees e WHERE EXISTS (

SELECT * FROM Orders oWHERE e.ID = o.EmployeeID AND OrderDate = '9/5/11')

Page 6: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t] )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?: \r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:( ?:\r\n)?[\t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-

... snip ...

"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t]) *))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]) +|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\ .(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z |(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:( ?:\r\n)?[ \t])*))*)?;\s*)

Page 7: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Talk Focus

• Internal C# DSLs– Less ramp-up– Automatic tooling support– Emergent in many new libraries

• Developer benefits > non-dev communication

Page 8: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

[Subject("Making a customer preferred")]public class when_a_regular_customer_is_made_preferred{ static Customer _customer;  Establish context = () => _customer = new Customer();  Because of = () => _customer.MakePreferred();  It should_mark_the_customer_as_preferred = () => _customer.IsPreferred.ShouldBeTrue();}

Page 9: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

people.Where(x => x.Age < 50)

from x in peoplewhere x.Age < 50select x

Page 10: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

LINQ

• Most(?) successful C# DSL

• Depending on C# 3.0 features– Anonymous Types– Extension Methods– Expression Trees

• Great DSL building blocks

Page 11: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

LINQ

people.Where(x => x.Age < 50)

from x in peoplewhere x.Age < 50select x

Page 12: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Expression Trees

Page 13: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Expression Trees

• Extracting AST-like structure from lambda expressions

• Expression<TDelegate>

Page 14: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Static Reflection

• Statically typed reference to code element• No magic strings• Tool support / Refactorability

• typeof(Person).GetProperty(”Name”); vs• GetProperty<Person>(x => x.Name);

Page 15: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

GetProperty<Person>(x => x.Name)

Page 16: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

GetPropertyNamepublic string GetPropertyName(Expression body){ // Unwrap boxing if (body is UnaryExpression) { body = ((UnaryExpression) body).Operand; }  var memberExpression = body as MemberExpression;  if (memberExpression == null) { throw new Exception("Descriptive exception message."); }  return memberExpression.Member.Name;}

Page 17: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

GetProperty<Person>(x => x.Friend.Name)

Page 18: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Object Printing

Page 19: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Recap

• We use DSLs almost every day

• Expression Trees are not (that) dangerous

• It doesn’t have to be hard to write a DSL!

Page 20: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

More Information?

• Domain Specific Languages by Martin Fowler

• Open Source Projects– Fubu– Most IoC containers– AutoMapper– AutoFixture– Fluent Nhibernate... and many more.

Page 21: Exploring C# DSLs: LINQ, Fluent Interfaces and Expression Trees

Questions?

Rasmus Kromann-Larsen

@[email protected]

www.rasmuskl.dk