实例化一个类使用反射 [英] Instantiating a class using Reflection
问题描述
假设我有三个项目在我的SLN。
(1)xyz.a {类库} {没有提及加}
(2)yzx.b {类库} {添加xyz.a参考}
(3)zxy.c {控制台应用程序} {添加xyz.a参考}
现在,我需要创建一个类居住在yzx.b从内部xyz.a使用反射实例。
和也本应是独立的文件夹/目录名。
即。甚至如果我改变yzx.b的目录的名称,它应该工作。
没有人有任何想法?
首先,Activator.CreateInstance()是一个正确的方式。
但是,有一个更有趣的方式是:
-
快
- 10倍
- 请不要换行异常 TargetInvocationException
只要创建EX pression调用构造函数:
公共静态函数功能:LT;反对[],对象> CreateConstructorDelegate(ConstructorInfo法)
{
变参=前pression.Parameter(typeof运算(对象[]),ARGS);
VAR参数=新的名单,其中,前pression>();
VAR methodParameters = method.GetParameters()了ToList()。
对于(VAR I = 0; I< methodParameters.Count;我++)
{
parameters.Add(前pression.Convert(
防爆pression.ArrayIndex(参数,防爆pression.Constant(I)),
methodParameters [I] .ParameterType));
}
VAR通话=前pression.Convert(出pression.New(方法参数)的typeof(对象));
防爆pression体=调用;
VAR callEx pression =前pression.Lambda< Func键<对象[],对象>>(机身,参数);
VAR的结果= callEx pression.Compile();
返回结果;
}
性能测试:
公共无效激活剂()
{
VAR秒表=新的秒表();
const int的时间=千万;
stopwatch.Start();
的for(int i = 0; I<次;我++)
{
变种V = Activator.CreateInstance(typeof运算(C));
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds +毫秒激活剂);
VAR德尔= CreateConstructorDelegate(typeof运算(C).GetConstructor(新类型[0]));
秒表=新的秒表();
stopwatch.Start();
变参=新对象[0];
的for(int i = 0; I<次;我++)
{
变种V =德尔(参数);
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds +毫秒EX pression);
}
输出:
1569ms与激活
与前pression 134ms
不过:</ P>
- 在C#3.0中,只有
- Complile()是长时间运行的操作
只是为了好奇。
Suppose I have three projects in my sln.
(1) xyz.a{Class Lib}{no reference added}
(2) yzx.b{Class Lib}{added the reference of xyz.a}
(3) zxy.c{Console App}{added the reference of xyz.a}
Now, I need to create the instance of a class residing in yzx.b from within xyz.a using reflection.
And also this should be independent of the folder/directory-names.
I.e. even If I change the name of the directory of yzx.b, it should work.
Does anyone have any idea?
First of all, Activator.CreateInstance() is a right way.
But, there is a more interesting way that is:
- 10 times faster
- Don't wrap exceptions in TargetInvocationException
Just create expression that calls constructor:
public static Func<object[], object> CreateConstructorDelegate(ConstructorInfo method)
{
var args = Expression.Parameter(typeof(object[]), "args");
var parameters = new List<Expression>();
var methodParameters = method.GetParameters().ToList();
for (var i = 0; i < methodParameters.Count; i++)
{
parameters.Add(Expression.Convert(
Expression.ArrayIndex(args, Expression.Constant(i)),
methodParameters[i].ParameterType));
}
var call = Expression.Convert(Expression.New(method, parameters), typeof(object));
Expression body = call;
var callExpression = Expression.Lambda<Func<object[], object>>(body, args);
var result = callExpression.Compile();
return result;
}
Performance test:
public void activator()
{
var stopwatch = new Stopwatch();
const int times = 10000000;
stopwatch.Start();
for (int i = 0; i < times; i++)
{
var v = Activator.CreateInstance(typeof (C));
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds + "ms with activator");
var del = CreateConstructorDelegate(typeof(C).GetConstructor(new Type[0]));
stopwatch = new Stopwatch();
stopwatch.Start();
var args = new object[0];
for (int i = 0; i < times; i++)
{
var v = del(args);
}
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds + "ms with expression");
}
Output:
1569ms with activator
134ms with expression
But:
- C# 3.0 only
- Complile() is long running operation
Just for curious.
这篇关于实例化一个类使用反射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!