Extending LLBLGenPro's ResultsetFields to work like List

These days I had a need to use ResultsetFields for fetching dynamic list. As you know, ResultsetFields derives from EntityFields2 (I am working with LLBLGenPro 2.0 .net 2) which is basically an array. There is nothing wrong with that, it is just you have to set its size beforehand (ok, you can explicitly expand or contract it later on) and you have to use indexes. Something like this:

ResultsetFields fields = new ResultsetFields(5);
fields[
0] = CountryEntity.Name;
fields[
1] = CountryEntity.Currency;
...

Again, nothing wrong with that, but why would one need to deal with indexes and sizes? Hence, here is my solution:

RhResultsetFields fields = new RhResultsetFields();
fields.Add(CountryEntity.Name);
fields.Add(CountryEntity.Currency);
...
fields.Contract();


See - no size, no indexes. The only thing added is the last line which contracts the array to the proper size and you have to call before using RhResultsetFields instance. This is necessary because I allocate a default size (10 - if not explicitly specified otherwise) at the instance creation and then expand it as necessary for a default size (5).

RhResultsetFields inherits from ResultsetFields and is only a thin wrapper around the base class - it adds dynamic expansion through many overloaded methods (generated out of DefineField methods) and that's it. Here is the code:

#if CF
[SD.LLBLGen.Pro.ORMSupportClasses.Serializable]
#else
[Serializable]
#endif
public class RhResultsetFields : ResultsetFields
{
private int lastFieldIndex = 0;
/// <summary>
/// Initializes a new instance of the RhResultsetFields class.
/// </summary>
public RhResultsetFields()
:
this(10)
{
}

/// <summary>Deserialization constructor</summary>
/// <param name="info">Info.</param>
/// <param name="context">Context.</param>
protected RhResultsetFields(SerializationInfo info, StreamingContext context): base(info, context)
{
lastFieldIndex
= (int)info.GetInt32("lastFieldIndex");
}

/// <summary>
/// Initializes a new instance of the RhResultsetFields class.
/// </summary>
public RhResultsetFields(int amount): base(amount)
{
}

public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
Contract();
base.GetObjectData(info, context);
info.AddValue(
"lastFieldIndex", lastFieldIndex);
}

public void Close()
{
base.Contract();
}

private int GetLastIndex()
{
lastFieldIndex
++;
if (lastFieldIndex >= base.Count)
Expand(
5);
return lastFieldIndex;
}

public int Add(IEntityField2 field)
{
base[GetLastIndex() - 1] = field;
return lastFieldIndex-1;
}

public int Add(IEntityField2 fieldToAdd, AggregateFunction aggregateFunctionToApply)
{
base.DefineField(fieldToAdd, GetLastIndex()-1, aggregateFunctionToApply);
return lastFieldIndex - 1;
}

public int Add(IEntityField2 fieldToAdd, string alias)
{
base.DefineField(fieldToAdd, GetLastIndex() - 1, alias);
return lastFieldIndex - 1;
}

public int Add(IEntityField2 fieldToAdd, string alias, AggregateFunction aggregateFunctionToApply)
{
base.DefineField(fieldToAdd, GetLastIndex() - 1, alias, aggregateFunctionToApply);
return lastFieldIndex - 1;
}

public int Add(IEntityField2 fieldToAdd, string alias, string entityAlias)
{
base.DefineField(fieldToAdd, GetLastIndex() - 1, alias, entityAlias);
return lastFieldIndex - 1;
}

public int Add(IEntityField2 fieldToAdd, string alias, string entityAlias, AggregateFunction aggregateFunctionToApply)
{
base.DefineField(fieldToAdd, GetLastIndex() - 1, alias, entityAlias, aggregateFunctionToApply);
return lastFieldIndex - 1;
}
}


There is one catch though. The original out of the box ResultsetFields doesn't define GetObjectData method as virtual. The method in question is required when deserializing an instance. Thus you have two options:
  1. Don't include this method at all. Your class won't be able to deserialize but otherwise you won't have problems.
  2. Modify the template that generates ResultsetFields class (yes, it is generated by LLBLGenPro generator). In my case (.net 2.0, C#, using adapters) this is resultsetFieldsAdapter.template file (located in .net2.x/c# template subfolder): just add keyword virtual to GetObjectData method - that's all.

Here you have it. You are free to use it and modify it. If you add interesting features I would be interested to see them :-)

Miha Markic

About me
Righthand
 
Microsoft MVP
 
Developer Express' DXSquad
INETA Country Leader for Slovenia
INETA Country Leader for Slovenia

Slovene Developer Users Group Lead
Friends of Red-Gate
LLBLGenPro Partner

Miha currently works as a free lance consultant and software developer specialized in .net area.
He graduated in Computer and information science at the University of Ljubljana, Slovenia. He has accumulated experience in various programming languages such as Java, Visual Basic 3-6 (MCP), Visual C++, Delphi, C# and VB.Net through years.
He has experience in practically all (technical) stages of project development, including planning, framework development, user interface, business processes, as well as testing and documenting. He has worked on big and small projects in Slovenia and abroad (e.g. participated in completing level 3 IS for the Nucor steel plant, Hertford, USA).
Currently he enjoys programming in .net environment using C#. Since 2000 he has been active in Developer Express' DX Squad and has been ECDL trainer and tester. He also gives lectures on conferences and other events in Slovenia.

Month List

Tag cloud

Most comments

Paulius Paulius
1 comments
us United States
Meh Meh
1 comments
us United States
bart dm bart dm
1 comments
nl Netherlands

RecentComments

Comment RSS