I have a class implementing an interface, which has a multi-parameter constructor, and a static sorted collection. This class is a Base Class which has many inherited classes.
internal class SCO : IVotable
{
public SCO(SPListItem item, List<Vote> votes)
{
//Initialize Object
}
public static List<T> SortedCollection<T>(SPListItemCollection items, ListSortType sortType, List<Vote> votes) where T : IVotable
{
var returnlist = new List<T>();
Type genericType = typeof(T);
for (int i = 0; i < items.Count; i++) { returnlist.Add((T)Activator.CreateInstance(genericType, new object[] { items[i], votes })); }
switch (sortType)
{
case ListSortType.Hot:
returnlist.Sort((p1, p2) => p2.HotScore.CompareTo(p1.HotScore));
break;
case ListSortType.Top:
returnlist.Sort((p1, p2) => p2.VoteTotal.CompareTo(p1.VoteTotal));
break;
case ListSortType.Recent:
returnlist.Sort((p1, p2) => p2.CreatedDate.CompareTo(p1.CreatedDate));
break;
}
return returnlist;
}
}
This allows me to do the following with any Child Class:
List<ChildClass> sortedClassList = ChildClass.SortedCollection<ChildClass>(listItems, sortType, votes);
My current reliance on Activator.CreateInstance worries me, as this is about 100 times slower than using Emit IL directly. I’ve been reading a few articles about Emit IL, and it seems fantastic for this solution.
I cannot seem to get it to work, however. When I try to instantiate ILGenerator gen = it tells me “Cannot access non-static field ‘method’ in static context”
My class isn’t static, neither are my constructors, and the static list show below isn’t interacting with Emit yet. How do I make this work?
Code thus far:
internal class SCO : IVotable
{
//Properties emittied
static ConstructorInfo ctor = typeof(SCO).GetConstructors()[1];
delegate SCO SCOCtor(SPListItem item, List<Vote> votes);
static SCOCtor SCOCtorDelegate;
DynamicMethod method = new DynamicMethod("CreateInstance", typeof (SCO),
new Type[] {typeof (SPListItem), typeof (List<Vote>)});
ILGenerator gen = method.GetILGenerator(); //Error here
//"Cannot access non-static field 'method' in static context"
private static SCO CreateInstance(SPListItem item, List<Vote> votes)
{
return SCOCtorDelegate(item, votes);
}
}
Blog for reference:
http://ayende.com/blog/3167/creating-objects-perf-implications
I have a drop-in replacement for Activator that uses IL generation hosted here on CodePlex. You can also get it via Nuget here (a single source file include, no assemblies).
The source code for FasterActivator is here.
Usage is something like what’s outlined below.
Oh, and here is a generic version that ought to be faster.
Hope this helps!