zoukankan      html  css  js  c++  java
  • 【转载】反射之实例创建ConstructorInfo.Invoke 对比 Activator.CreateInstance

    About a year ago I blogged about different methods of object instantiation and that compiled lambda expressions should be preferred in case same type is instantiated frequently and instantiation performance is critical. However, on many occasions dealing with expression compilation is not worth it, and creating an instance using reflection is simple and usually good enough. Then Activator.CreateInstance seems to be a default choice for such operations. What can be simpler than this call?

    1
    var instance = Activator.CreateInstance<SomeType>();

    The problem with this approach is its false sense of simplicity: it gives an impression that the instance will be created without any additional information, for example initialization parameters.

    To prove how misleading such simplicity can be you just need to try creating an instance of a string:

    1
    var instance = Activator.CreateInstance<string>();

    The line above causes MissingMethodException with message “No parameterless constructor defined for this object”. And of course, System.String does not have a default constructor.

    So what to do? We can of course say that if a class does not have default constructor, then instantiating it in such way is a bad idea, and those classes are just not intended to be used with code trying to create class instances in such manner. However, I bet that more often than not the semantics behind the code “Activator.CreateInstance<T>” is “give me some instance of T, I don’t care about how you create it”. Under such conditions invoking an arbitrary class constructor is preferred over dealing with MissingMethodException. So why not using ConstructorInfo.Invoke then?

    Of course, once you settle for ConstructorInfo, you have to decide what constructor overload to use. But this is not really different from choosing parameterless overload of Activator.CreateInstance. In many cases you don’t choose default constructor because this the state of the object you need – you choose it because you don’t care about the state and thus would like to run the simplest form of creation. Applying the same logic to classes without default constructor we can choose a constructor overload with fewest number of parameters:

    1
    2
    3
    4
    var constructor = typeof(T).GetConstructors().OrderBy(c => c.GetParameters().Length).FirstOrDefault();
    if (constructor == null)
        throw new MissingMethodException("No public constructor defined for this object");
    var instance = constructor.Invoke(new object[constructor.GetParameters().Length]);

    One area when this approach can be useful is if there is a need to create an instance of an anonymous type (I know it’s a very special need – why on earth will you want to create an instance of an anonymous type? – but I’ve come across a situation):

    1
    2
    3
    var o = new { A = "a", B = 1 };
    var constructor = o.GetType().GetConstructors()[0];
    var instance = constructor.Invoke(new object[constructor.GetParameters().Length]);

    Anonymous types don’t get a parameterless constructor, but there is a constructor with a number of arguments equal to the number of type’s properties. I would however use syntax GetConstructors().OrderBy(c => c.GetParameters().Length).FirstOrDefault() that can be applied in general case.

  • 相关阅读:
    Structured Streaming watermark总结
    技术实践第三期|HashTag在Redis集群环境下的使用
    元宇宙带来沉浸式智能登录?你学会了吗?
    技术实践第一期|友盟+开发者平台Node.js重构之路
    2021年度友盟+ APP消息推送白皮书:工作日68点通勤时间消息送达率每日最高
    技术实践第二期|Flutter异常捕获
    注意啦!还没有支持64位系统的App开发者,务必在12月底前完成这件事!
    一位大牛对于写技术博客的一些建议
    国内常用源开发环境换源(flutter换源,python换源,Linux换源,npm换源)
    初识Socket通讯编程(一)
  • 原文地址:https://www.cnblogs.com/zhxhdean/p/3077332.html
Copyright © 2011-2022 走看看