详解C#特性和反射(四)

  本篇内容是特性和反射的最后一篇内容,前面三篇文章:

详解C#特性和反射(一)

详解C#特性和反射(二)

详解C#特性和反射(三)

 

  一、晚期绑定(Late Binding)是一种在编译时不知道类型及其成员,而在运行时创建指定类型的实例并调用其成员的技术,使用命名空间System中的Activator类来实现晚期绑定,例如:

    Type myType = Type.GetType(myClassName);  //首先获取类型信息
    object myObj = Activator.CreateInstance(myType);  //通过Activator根据类型信息创建对象
    //如果获取的类型可以获取到,即位于当前程序集,可以使用强制转换或as运算符得到该类型的变量,然后直接调用该对象的成员:
    //MyClass myClass = (MyClass)myObj;
    //也可以使用CreateInstance的泛型重载方法直接获取该类型的变量:
    //MyClass myClass = Activator.CreateInstance<MyClass>();
    //如果获取的类型不确定或当前程序编译时并没有引入该类型所在的命名空间,则需要通过反射访问该类型的成员:
    MethodInfo methodInfo = myType.GetMethod(methodName);  //获取类型中的方法信息
    methodInfo.Invoke(myObj, null);  //调用类型中的无参实例方法

   ※静态方法CreateInstance会调用匹配度最高的构造函数构建对象,例子中的CreateInstance(Type type)和CreateInstance<T>()只会调用目标类型中无参的公有构造函数,当目标类型中没有无参的公有构造函数时会抛出异常MissingMethodException;Activator类中提供多个CreateInstance的重载方法以调用不同的构造函数并传入参数,这里不再一一介绍,用到时查看定义即可看到所有的方法声明;

  二、使用晚期绑定技术也会打破单例模式中的对象唯一性:

    public class MyClass
    {
        public static MyClass Instace = new MyClass();
        private MyClass()
        {
            Console.WriteLine("MyClass's Constructor Execute.");
        }
        public int MyFiled;
    }

    public class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Access the static member Instace of MyClass.");
            MyClass.Instace.MyFiled = 10;
            Console.WriteLine("Use the Activator class to create instance of MyClass.");
       //通过CreateInstance的重载方法调用目标类型的私有构造函数 MyClass myObj
= (MyClass)Activator.CreateInstance(typeof(MyClass), true); Console.WriteLine($"Instace of MyClass's MyFiled is {MyClass.Instace.MyFiled}, myObj's MyFiled is {myObj.MyFiled}."); Console.Read(); } }

  输出结果为(在.Net Core下运行,不同平台下静态成员的初始化时机略有不同,会导致这里第一行和第二行输出顺序不一致):

Access the static member Instace of MyClass.
MyClass's Constructor Execute.
Use the Activator class to create instance of MyClass.
MyClass's Constructor Execute.
Instace of MyClass's MyFiled is 10, myObj's MyFiled is 0.

因此在使用单例模式时,应当避免使用晚期绑定创建对象,而应使用反射获取单例中的静态成员Instance;

 


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的认可是我写作的最大动力!

作者:Minotauros
出处:https://www.cnblogs.com/minotauros/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted @ 2018-10-09 16:50 Minotauros 阅读(...) 评论(...) 编辑 收藏