Showing posts with label Lambda. Show all posts
Showing posts with label Lambda. Show all posts

Wednesday, June 23, 2010

Compile-safe MemberInfo Selection

I have been playing around with Windows Forms in .NET and in particular the ComboBox control.

I decided to initialise the combo box like so:

private void SetComboData(IList<SupporterRecord> supporters)
{
var bindingSource = new BindingSource { DataSource = supporters };
comboBox1.DisplayMember = "OpportunityName";
comboBox1.ValueMember = "SupporterId";
comboBox1.DataSource = bindingSource;
}



Notice how the DisplayMember and ValueMember variables are being set by hardcoding the string name of the property that exists on the SupporterRecord class.

This is horrible because I get no compile-time checking of the Property names.

I want to be able to use a Lambda expression to do something like this:


// get the Property item via reflection
MemberInfo member = SupporterNumber.GetMemberinfo(s &eq;> s.OpportunityName);

// and get the name of the property
string name = member.Name;


I found a code snippet on the StackOverflow site to almost do this.

Thinking about this further I also want to be able to do this in the general case for all object types. In comes Extension Methods.


public static class ClassExtensions
{
public static MemberInfo GetMemberInfo<TSupporterRecord>(this TSupporterRecord r, Expression<func<TSupporterRecord, object>> expression)
{
var member = expression.Body as MemberExpression;
if (member == null)
throw new ArgumentException("expression returns no member.", "expression");

return member.Member;
}
}


Usage is as follows:


private void SetComboData(IList<SupporterRecord> supporters){
var bindingSource = new BindingSource { DataSource = supporters };
comboBox1.DisplayMember = ((SupporterRecord)null).GetMemberInfo(s => s.OpportunityName).Name;
comboBox1.ValueMember = ((SupporterRecord)null).GetMemberInfo(s => s.SupporterId).Name;
comboBox1.DataSource = bindingSource;
}



Now it is not entirely the way I want it but it is getting close as I want:


MemberInfo member = SupporterNumber.GetMemberinfo(s => s.OpportunityName);


which is a static method on the class so I started Googling for static extension methods but there is currently no implementation of this, but a number of people saying how cool it would be to have it.

Maybe in later releases of .NET we will see this and I'll be able to perfect my API.

Cheers

Tuesday, March 17, 2009

Layer Transparent Paging

I am currently working on an issue where I am processing large amounts of data. So I have decided to implement a paging strategy.

Now my issue was that I am wanting to pass this paging strategy from my Data Access Layer (DAL) to my Buisness Logic Layer (BLL) without exposing my underlying framework which happens to be NHibernate.

So I have devised the interface:

public interface IPagedResult<T> : IEnumerator<IList<T>>
{
int PageSize { get; }
IPageSession Session { get; }
}

This I can then pass through to my BLL to iterate through the results like so:

using (var pagedResults = DAL.GetPagedResultsForSomething())
{
while (pagedResults.MoveNext())
{
foreach (var item in pagedResults.Current)
{
doSomethingWithItem(item);
}
}
}


Allowing the PagedResult object to handle all session and transaction issues.

I also devised a way to put my query into the PagedResult object using Lambdas:

public class PagedResult<T> : IPagedResult<T>
{
private int currentResult = 0;
public delegate ICriteria QueryFunction(ISession session);

public PagedResult(int pageSize, ISession session, QueryFunction query)
{ ... snip ... }

public vool MoveNext()
{
try
{
Current = query(session)
.SetFirstResult(currentResult)
.setMaxResults(PageSize)
.List<Statement<T>();

if ((Current == null) (Current.Count == 0))
{
Current = null;
return false;
}

currentResult += PageSize;
return true;
}
catch
{
session.Transaction.RollBack();
throw;
}
}

... snip ...
}


This allows me to use it as such:

var statementId = 1;
var pageSize = 10;
new PagedResult<Statement>(
pageSize,
new Session(),
s =>
s.CreateCriteria(typeof(Statement), "statement")
.SetResultTransformer(CriteriaUtil.DistinctRootEntity)
.Add(Restrictions.Eq("statement.Id", statementId))
);
What do people think?

Cheers,

Erik