Getting started ๏ฟฝ jagregory/fluent-nhibernate Wiki ๏ฟฝ GitHub:

To start with we've mapped the Id column, and told Fluent NHibernate that it's actually an identifier. The x in this example is an instance of Employee that Fluent NHibernate uses to retrieve the property details from, so all you're really doing here is telling it which property you want your Id to be. Fluent NHibernate will see that your Id property has a type of int, and it'll automatically decide that it should be mapped as an auto-incrementing identity in the database - handy!

That's great if lambdas are second nature.  If they're not, it could use a little more explanation.  What's important to realize first is that Fluent NHibernate is calling functions that live in FluentNHibernate.Mapping.ClassMap.  So a line like...

Id(d => d.Id);

... in your Fluent NHibernate mapping object is extending ClassMap and then calling its own function Id, as pictured below (if Blogger would stop eating all my less than and greater than symbols):

public virtual IdentityPart Id(Expression> memberExpression);

Why is that important?  Well, the "Expression" parameter has to be a lambda expression.  As things are set up, there's simply no way around it.  So forget, for the moment, how lambda's save space or provide some justifiable shortcut.  Know that the way Fluent NHib is written, you're stuck.  Here's a snippet for Expression, which is in System.Linq.Expressions...


namespace System.Linq.Expressions
{
    // Summary:
    //     Represents a strongly typed lambda expression as a data structure in the
    //     form of an expression tree. This class cannot be inherited.
    //
    // Type parameters:
    //   TDelegate:
    //     The type of the delegate that the System.Linq.Expressions.Expression
    //     represents.
    public sealed class Expression : LambdaExpression


...


This "do it because you gotta" directive seems to be a more productive approach than reading MSDN on lambdas.  I mean, honestly, this explanation is not useful:


Remarks
The LambdaExpression type represents a lambda expression in the form of an expression tree. The Expression type, which derives from LambdaExpression and captures the type of the lambda expression more explicitly, can also be used to represent a lambda expression. At runtime, an expression tree node that represents a lambda expression is always of type Expression.

The value of the NodeType property of a LambdaExpression is Lambda.

Use the Lambda factory methods to create a LambdaExpression object.

Lambdas use lambdas to create lambdas, which lambda lambda lambda.  It's like watching the smurfs.

Regardless, let's explore a little further, and read up on Expressions...

Remarks
The LambdaExpression type represents a lambda expression in the form of an expression tree. The Expression type, which derives from LambdaExpression and captures the type of the lambda expression more explicitly, can also be used to represent a lambda expression. At runtime, an expression tree node that represents a lambda expression is always of type Expression.

The value of the NodeType property of a LambdaExpression is Lambda.

Use the Lambda factory methods to create a LambdaExpression object.

Even better, here's a helpful post called "Learning C# lambda syntax from delegates", that, though the code is a little jammed together, steps you through the evolution from straight functions to anonymous functions/delegates to the specific anon funct of the lambda expression.  (Are we there yet, Papa Lambda?)

This line of progression of code in particular is especially clever and helpful:

// conventional function, predefined
var widgets300GramsOrLess = Array.FindAll(widgets, Weighs300GramsOrLess); 

// delegate
var widgets300GramsOrLess = 
  Array.FindAll(widgets, delegate(Widget widget) { return widget.WeightInGrams <= 300; });  

// lambda
var widgets300GramsOrLess = 
  Array.FindAll(widgets, widget => widget.WeightInGrams <= 300); 

The first less than in that last line is a lambda, of course, and the less than plus equal to is just that, a simple less than or equal to.

So in a sense, you should be able to turn a line like from FluNHib...

this.Id(d => d.Id);

... into this with a delegate...

this.Id(delegate(Address d)   {
    return d.Id;
});

... except that you can't, because, as I wrote earlier, FluNHib expects an System.Linq.Expressions.Expression, and you'll instead receive an "An anonymous method expression cannot be converted to an expression tree" error.

It looks like the Expression, as that earlier definition would suggest, can take in a single parameter and can only be a single line.  So something like this would be a valid alternative:

this.Id(d => "spam".ToUpper() + " :: " + d.FirstName);

... but something longer like this obviously wouldn't:

this.Id(d => string strTemp = "spam".ToUpper() + " :: " + d.FirstName; return strSpam);

Make sense?  Great.  Enjoy your lambdas.

Labels: ,