实例化使用的类的反思(Instantiating a class using Reflection)

2019-08-05 19:57发布

假设我有我的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}

现在,我需要创建一个从内xyz.a使用反射居住在yzx.b一个类的实例。

而这也应该是独立的文件夹/目录名。

也就是说,即使我改变yzx.b的目录的名称,它应该工作。

有谁有想法吗?

Answer 1:

首先,Activator.CreateInstance() 是正确的方式。

但是,还有一个是更有趣的方式:

  • 快10倍
  • 不裹在TargetInvocationException例外

只要创建表达式调用构造函数:

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;
}

性能测试:

    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");
    }

输出:

1569ms with activator
134ms with expression

但:

  • C#3.0中,只有
  • 请编译()是长时间运行的操作

只是为了好奇。



Answer 2:

您可能要检查出Activator.CreateInstance()方法。 只是通过它的组装和类的名称。

如果你没有一个编译时参考汇编,你仍然可以用它引用在运行时Assembly.Load() 。



Answer 3:

您可以使用Activator.CreateInstance轻松地创建一个实例(这也不会反射信息的各种缓存,使千呼万唤快),或Type.GetConstructor如果要反映过来的构造本身以及直接运行它(通过ConstructorInfo。调用 )



文章来源: Instantiating a class using Reflection