Showing posts with label C#. Show all posts
Showing posts with label C#. 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

Monday, March 9, 2009

Handling Cartesian Products in NHibernate

I have been using NHibernate for a little while now, but I am mostly self taught in this. I have recently done a course on ADO.NET to try and understand some of the basics of data access that I may have missed, and also to get a little of an understanding of the core technologies behind NHibernate.

I was reading a post on Eager Loading by Derik Whittaker on the Devlicio.us site where Derik was talking about returning a list of objects using the CreateCriteria query method. His issue was that when he used Eager Loading, he got more rows back then expected. This was due to the Cartesian Product issue where the join on the tables caused extra rows to be returned for a single object and NHibernate hydrating an object for each row. His solution was to include the command:

.SetResultTransformer( new DistinctRootEntityResultTransformer() )

which can be shortened to:

.SetResultTransformer(CriteriaUtil.DistinctRootEntity)

While reading through the comments on this post I found that someone had posted:

Why didn't you use the CreateMultiCriteria method?

This got me thinking. I have heard of MultiCriteria before but never realised that you could use it to solve the Cartesian Product problem before.

So to Google I went and I found the NHibernate Documentation and to my surprise I found the example under CreateMultiQuery. I had never found this before because I had always limited my reading to the CreateMultiCriteria (which is a more fluent version of MultiQuery).

So now the challenge I have set myself is to sit down and try to get some examples of this working.

Till next time.

Erik

Thursday, March 5, 2009

New Findings: AOP & PostSharp

I was just browsing through the latest MSDN magazine today while waiting for a rather long integration test to run, and I found an article on Aspect-Oriented Programming (AOP). Now I have heard of AOP and have been told that it is a very effective programming paradigm, but have never fully looked into it before. In the article the author (Scott Michell) presents an open source framework called PostSharp. Now I spent a good while looking through the website and some examples and I am impressed. The power with PostSharp is that you define a custom attribute which extends from one of PostSharps base classes and you can write code for cross cutting concerns such as logging, security, etc into this attribute and place the attribute on the properties in your class and the PostSharp.Core puts your code into the class at compile time.

I'm looking forward to sitting down and having a play with this framework as it looks really positive. Anything that promises to improve my coding practices is worth a bit of my time.