图片 6

跟小静读CLR via C#(11)-无参属性、索引器

做项目时偶尔B类赋值给A类,碰巧A和B类型很多属性字段名是一样的,或者只是大小写不一样,这是可以利用泛型,反射来写一个自动化赋值的方法。

提起属性,我们都不陌生。它用起来就像访问public数据成员一样,但实际上是调用了内部定义的相应方法。通过使用属性保持了较好的数据封装,而且访问很方便,接下来我们共同复习以下CLR允许定义的两种属性:无参属性和有参属性(索引器)。

下面方法不考虑大小写不一样的情况,如果要考虑,可以使用字符串方法
ToUpper() 、ToLower() 后,对比字段名是否一样。


 public class MapperModel
    {
        /// <summary>
        /// B对象相同属性赋值给A对象, 
        /// </summary>
        /// <typeparam name="A">类型A</typeparam>
        /// <typeparam name="B">类型B</typeparam>
        /// <param name="b">B对象</param>
        /// <returns>返回创建的新A对象</returns>
        public static A Mapper<A, B>(B b)
        {
            A a = Activator.CreateInstance<A>();
            try
            {
                Type Typeb = b.GetType();//获得类型  
                Type Typea = typeof(A);
                foreach (PropertyInfo bp in Typeb.GetProperties())//获得类型的属性字段  
                {
                    foreach (PropertyInfo ap in Typea.GetProperties())
                    {
                        if (ap.Name == bp.Name)//判断属性名是否相同  
                        {                          
                            if (ap.GetSetMethod()!= null)
                            {
                                if (bp.GetGetMethod()!=null)
                                {
                                    ap.SetValue(a, bp.GetValue(b, null), null);//获得b对象属性的值复制给a对象的属性   }
                                }

                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return a;
        }
    }

一、 无参属性

值得注意的地方,属性到底有没有Get或者Set方法 ?B属性Set访问器是非公共的或不存在
则会赋值时出现异常。同理:A属性如果 Get
访问器是非公共的或不存在,则取值时出现异常

1. 定义属性

无参属性就是我们最常见的属性方式,在赋值时可以加入一定的逻辑判断。属性的定义其实不复杂,先看个直观的例子:

图片 1

说明:

  • 属性要定义名称和类型,且类型不能是void。
  • 属性是不能重载的。我们不能定义名称相同、类型不同的两个属性。
  • 属性一般需要定义get和set方法来操作类内部的私有支持字段,如上面的_name,
    _age等。Set方法中包含隐藏参数叫做value,表示赋给属性的值。
  • 只读只写属性:可以通过省略set来定义只读属性(如Count属性),或者省略get来定义只写属性。
  • CLR支持静态、实例、抽象和虚属性。例子中的Name和Age就是我们最常用的实例属性,Count就是静态只读属性的例子。

调用:使用属性时会产生相应的智能感知,就像使用公用字段一样:

图片 2

运行结果:

图片 3

因此上面使用了 GetSetMethod(),GetGetMethod()做判断。如果Get 、Set
访问器不能正常获取,则返回为null。

2. 编译结果

通过ILDasm.exe查看元数据,

图片 4

我们发现多了以下几项:

① 如果属性包含get访问器,则会生成“get_属性名
的方法,如get_Age;

② 如果属性包含set访问器,则会生成“set_属性名”的方法,如set_Name;


元数据中的属性定义项,包含了一些标记和属性类型,并引用了get或set访问器方法,这样就使属性和访问器之间产生了关联。例如Count属性定义项内容:

   
图片 5

 

3. 自动实现的属性——AIP

AIP(Automatically Implemented
Property)是实现属性的一种更简洁的方式。例如上面的Student类,可以简化为:

图片 6

调用方式和运行结果与之前一致,这里就不赘述了。

简洁固然好,但要注意以下几点:

① AIP的get和set方法中不能添加断点调试。


AIP属性必须是同时可读可写的。如果只定义get或者只定义set,则必须两个都显式实现,不能使用AIP。


想要序列化或者反序列化的类中,不要定义AIP。因为运行时序列化引擎将字段名持久化到了序列化流中,而且每次编译时这个名字还有可能改变。

发表评论

电子邮件地址不会被公开。 必填项已用*标注