Can someone explain this Syntax?

Can someone explain this Syntax?

Old forum URL: forums.lhotka.net/forums/t/7217.aspx


Mark Richardson posted on Thursday, July 02, 2009

Hello Guys,
 
I am pretty new to this style of syntax?

Can someone explain it to me in the most "generic" terms what the following piece of code is doing?
 
///////////////////////////////////////////////////////////////////////
What is this doing?
///////////////////////////////////////////////////////////////////////
private static PropertyInfo<string> CityProperty = RegisterProperty<string>(c => c.City); //new PropertyInfo<string>("City", "City"));
///////////////////////////////////////////////////////////////////////
 
 
///////////////////////////////////////////////////////////////////////
//I understand the code below.
///////////////////////////////////////////////////////////////////////
public string City
{
    get
   {
       return GetProperty(CityProperty);
   }
   set
   {
       SetProperty(CityProperty, value);
   }
}

RockfordLhotka replied on Thursday, July 02, 2009

I recommend reading the Expert 2008 Business Objects book, as this is discussed in many places through the book.

The short answer is that the static PropertyInfo<T> field maintains metadata about your property, and acts as a strongly-typed token you can use instead of using string literal values all over the place.

Without the PropertyInfo<T> field your property would look like this:

public string City
{
  get { return GetProperty<string>("City"); }
  set { SetProperty<string>("City", value); }
}

You'd have to supply the property type because it couldn't be inferred, and you'd have to supply the property name as a hard-to-maintain string literal. Very bad.

Mark Richardson replied on Thursday, July 02, 2009

Rocky,
 
I understand that, I was more confused with the Lambda code.
I have read about Lambda, and I get even more confused reading about it.
 
I was trying to see if someone can explain the Lambda parts of it.
 
Sorry for the confusion.
 
Mark

RockfordLhotka replied on Thursday, July 02, 2009

Lambdas can be hard to read to start - no doubt there!

the (c => c.Id) is a simple lambda expression where 'c' represents an instance of the current business object type. So that expression is returning the Id property of the current business object type.

The RegisterProperty() method uses some reflection behind the scenes to take that property and get a reflection object that describes the property, which allows us to pull out the property's name and data type.

The real value here is that the 'c.Id' part is a strongly-typed, compiler-checked construct. And even better, if you do a symbolic rename (rename refactor) on the property, the rename will fix this code too, where it wouldn't fix a string literal.

So while the syntax looks a bit odd the first time you see it, the value in terms of maintainabilty is really high, and so it is (imo) worth using.

Mark Richardson replied on Thursday, July 02, 2009

Rocky,

Thanks for the response.

But how does "(c => c.Id)" know that "c" represents an instance of the current business object type?

It looks like you just magically declared "c" and something automatically knew it's type.

What am I missing here?

Also,

DataService is a proxy class to the webservice you created.
I don't see a WebServiceSoapClient method inside the service, where is this coming from?


var
svc = new DataService.WebServiceSoapClient();

What is this?

What is the (o,e) part?
How does o and e get a value and where from?

svc.GetDataCompleted += (o, e) =>
{

if (e.Error == null)

{

using (BypassPropertyChecks)

{

Id = e.Result.Id;

Name = e.Result.Name;

City = e.Result.City;

}

}

handler(this, e.Error);

};

Also,

How does to know to call the "GetData" method on the service?
svc.GetDataAsync(criteria.Value);

sergeyb replied on Thursday, July 02, 2009

It is typed in framework based on generic type parameter for BB / you class.

 

Sergey Barskiy

Principal Consultant

office: 678.405.0687 | mobile: 404.388.1899

cid:_2_0648EA840648E85C001BBCB886257279
Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: Mark Richardson [mailto:cslanet@lhotka.net]
Sent: Thursday, July 02, 2009 2:47 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] Can someone explain this Syntax?

 

Rocky,


Thanks for the response.


But how does "(c => c.Id)" know that "c" represents an instance of the current business object type?

It looks like you just magically declared "c" and something automatically knew it's type.

What am I missing here?



Mark Richardson replied on Thursday, July 02, 2009

Not following you here?

sergeyb replied on Thursday, July 02, 2009

Look in CSLA business base’s register property – it will make more sense.

 

 

Sergey Barskiy

Principal Consultant

office: 678.405.0687 | mobile: 404.388.1899

cid:_2_0648EA840648E85C001BBCB886257279
Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: Mark Richardson [mailto:cslanet@lhotka.net]
Sent: Thursday, July 02, 2009 5:08 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] RE: Can someone explain this Syntax?

 

Not following you here?



robdal replied on Thursday, July 02, 2009

Hope this helps: (this sample is taken from the tutorial Lambda Expression from LearnVisualStudio.com
class Class1
{
// step 1
public delegate bool FunctionForNumber(int number);

// step 2
public static int[] PerformOperationOnNumberArray(int[] myNumbers, FunctionForNumber myFunction)
{
System.Collections.ArrayList myList = new System.Collections.ArrayList();
foreach (int number in myNumbers)
{
if (myFunction(number))
{
myList.Add(number);
}
}

return (int[])myList.ToArray(typeof(int));
}
// step 3
public static bool GreaterThan10(int number)
{
return number > 10;
}

static void Main(string[] args)
{
int[] myNumbers = { 1, 2, 15, 22 };
//option 1
//int[] numbersA = PerformOperationOnNumberArray(myNumbers, GreaterThan10);
//option 2
//int[] numbersA = PerformOperationOnNumberArray(myNumbers, delegate(int number) { return number > 10; });
//option 3
int[] numbersA = PerformOperationOnNumberArray(myNumbers, (number => number > 10));

foreach (int number in numbersA)
{
Console.WriteLine(number);
}

Console.ReadLine();
}
}

Similarly, if you have a Person class with lastname and firstname you can do something like:
public class PersonManager
{
private List people = new List();
public PersonManager()
{
Person person = new Person();
person.FirstName = "Mark";
person.LastName = "Richardson";

person = new Person();
person.FirstName = "Roberto";
person.LastName = "Dalmonte";

person = new Person();
person.FirstName = "Ricky";
person.LastName = "Lohtka";
}
public Person GetLastNameStartsWithR()
{
return people.First(p => p.LastName.StartsWith("R"));
}
}

Roberto Dalmonte

Mark Richardson replied on Thursday, July 09, 2009

Rocky,

Below, you said
 
the (c => c.Id) is a simple lambda expression where 'c' represents an instance of the current business object type. So that expression is returning the Id property of the current business object type.

What is confusing me here, is how does it know that "c" is reference to the business object.

If I always do a (a => a.id)

Is "a" the same as going "this.id"

I hope I explained this correctly.

Mark
 
RockfordLhotka:

 

Lambdas can be hard to read to start - no doubt there!

the (c => c.Id) is a simple lambda expression where 'c' represents an instance of the current business object type. So that expression is returning the Id property of the current business object type.

The RegisterProperty() method uses some reflection behind the scenes to take that property and get a reflection object that describes the property, which allows us to pull out the property's name and data type.

The real value here is that the 'c.Id' part is a strongly-typed, compiler-checked construct. And even better, if you do a symbolic rename (rename refactor) on the property, the rename will fix this code too, where it wouldn't fix a string literal.

So while the syntax looks a bit odd the first time you see it, the value in terms of maintainabilty is really high, and so it is (imo) worth using.

RockfordLhotka replied on Thursday, July 09, 2009

The identifier you use (‘c’ in my case) is arbitrary. It is like the identifier you use for a type parameter in a generic – you can use whatever you’d like.

 

The type of the identifier is determined by the declaration of the parameter as defined by the RegisterProperty() method. As Sergey suggested, you can look in BusinessBase<T> to see how RegisterProperty() is defined, and what you’ll discover is that this parameter matches a specific method signature, where the type is defined as being the type of the business class.

 

This allows the compiler to infer the type of your identifier (‘c’) as being the type of the business class.

 

Rocky

 

Copyright (c) Marimer LLC