[英]Using IL Emit to replace Activator.CreateInstance
我有一個實現接口的類,它有一個多參數構造函數和一個靜態排序集合。 此類是一個具有許多繼承類的基類。
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;
}
}
這允許我對任何子類進行以下操作:
List<ChildClass> sortedClassList = ChildClass.SortedCollection<ChildClass>(listItems, sortType, votes);
我目前對Activator.CreateInstance的依賴讓我擔心,因為這比直接使用Emit IL慢大約100倍。 我一直在閱讀一些關於Emit IL的文章,這個解決方案看起來很棒。
但是,我似乎無法讓它工作。 當我嘗試實例化ILGenerator gen =
它告訴我“無法在靜態上下文中訪問非靜態字段'方法”
我的類不是靜態的,也不是我的構造函數,下面顯示的靜態列表還沒有與Emit交互。 我該如何工作?
代碼到目前為止:
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);
}
}
博客供參考: http : //ayende.com/blog/3167/creating-objects-perf-implications
我有激活劑直接替代使用IL代托管在這里在CodePlex上。 你也可以通過Nuget 在這里獲得它(單個源文件包括,沒有程序集)。
FasterActivator的源代碼在這里 。
用法類似於下面概述的內容。
private static readonly Dictionary<Type, DynamicCreationDelegate> _cachedCreationDelegates = new Dictionary<Type, DynamicCreationDelegate>();
private static DynamicCreationDelegate CreateOrGet(Type typeToCreate)
{
DynamicCreationDelegate result = null;
if (!_cachedCreationDelegates.TryGetValue(typeToCreate, out result))
{
result = FastActivator.GenerateDelegate(typeToCreate,
/* List of types that make up the constructor signature of the type being constructed */
typeof(SPListItem), typeof(List<Vote>));
_cachedCreationDelegates.Add(result);
}
return result;
}
// Usage
for (int i = 0; i < items.Count; i++)
{
var creationDelegate = CreateOrGet(typeof(genericType));
returnlist.Add((T)creationDelegate(new object[] { items[i], votes }));
}
哦,這是一個應該更快的通用版本。
private static readonly Func<SPListItem, List<T>, T> _creationFunc;
private static Func<SPListItem, List<T>, T> CreateOrGetFunc()
{
if (!_creationFunc == null)
_creationFunc = FastActivator.GenerateFunc<Func<SPListItem, List<T>, T>>(/* IL generator knows all type info from generic params now */);
return _creationFunc;
}
// Usage
for (int i = 0; i < items.Count; i++)
{
var creationFunc = CreateOrGetFunc();
returnlist.Add(creationFunc(items[i], votes ));
}
希望這可以幫助!
我看到你有一個答案。 我剛剛向github上傳了一個輔助類的代碼到IL構造函數調用(我本來應該這樣做過,但是錯過了一個很好的理由):
用法是這樣的:
// suppose you want to call the constructor for this class
// but generalizing the return to ISomeInterface
public class AClass : ISomeInterface
{
public class(int intParam, String stringParam) { }
}
// construct the factory method Func<int, string, ISomeInterface>
var createAClassInstance = ReflectionHelper
// return type + constructor params
.CreateFactoryMethod<ISomeInterface, int, string>(typeof(AClass));
var instance = createAClassInstance(10, "hello constructor");
如果你願意接受一些重復,那么你可以使用代理,而不是處理IL(它可以快速復雜,如你所發現的那樣)。 就像是:
internal class SCO : IVotable
{
protected static List<T> SortedCollection<T>
(SPListItemCollection items, ListSortType sortType, List<Vote> votes,
Func<SPListItem, List<Vote>, T> factory) where T : IVotable
{
var returnlist = new List<T>();
Type genericType = typeof(T);
for (int i = 0; i < items.Count; i++)
returnlist.Add(factory(items[i], votes));
// etc.
}
}
class ChildClass : SCO
{
public static List<ChildClass> SortedCollection
(SPListItemCollection items, ListSortType sortType, List<Vote> votes)
{
return SCO.SortedCollection<ChildClass>(
items, sortType, votes, (i, vs) => new ChildClass(i, vs));
}
}
這樣做應該非常快,甚至可能比使用IL發射時稍快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.