码迷,mamicode.com
首页 > 其他好文 > 详细

类型构造器-记一次悲惨经历,论我是如何用静态构造器来作死的

时间:2015-05-28 21:11:50      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

在写一个wp的论坛程序时,我定义了几个类。一个是管理类(即Manager),这个管理类不能被实例化,它管理着论坛的板块类型(PlateCategory)和板块(Plate)的集合,即

static PlatesManager() {       
   //…
   private static ObservableCollection<PlateCategory> PlateCategories;       
  private static ObservableCollection<Plate> Plates;     
   public static ObservableCollection<PlateCategory> GetPlateCategories() {    
         return PlateCategories;      
   }      
   public static ObservableCollection<Plate> GetPlates() {         
    return Plates;      
   } }

当然,这没什么,很正常不过,我又想,如果每次创建一个新的Plate和PlateCategory类都要调用一下这个Manager类的Add方法,感觉好像很麻烦,于是我就在Plate和PlateCategory的构造方法和析构方法中添加了如下代码:

        public PlateCategory() {
            PlatesManager.AddPlateCategory(this);
        }

        ~PlateCategory() {
            PlatesManager.RemovePlateCategory(this);
        }

这个还好,我也自我感觉良好。不过比较诡异的一幕要发生了,我不知怎么地居然还想弄一个仓库类,觉得这样比较又逼格。于是创建了IRepository接口,并创建了两个仓库PlateRepository和PlateCategoryRepository。接口定义了增删改查操作:

public interface IRepository<T> {
        IEnumerable<T> GetAll();
        T Get(T t);
        T Get(int id);
        T Add(T t);
        bool Remove(T t);
        bool Remove(int id);
        bool Update(T t);
}

然后我把这两个仓库添加到了Manager管理类中,并写下了静态构造器,也成为类型构造器以及增删改查:

public class PlatesManager {

        static PlatesManager() {
            PlateRepo = PlateRepository.GetInstance();
            PlateCateRepo = PlateCategoryRepository.GetInstance();

            PlateCategories = PlateCateRepo.GetAll() as ObservableCollection<PlateCategory>;
            Plates = PlateRepo.GetAll() as ObservableCollection<Plate>;

            PlateCategories = new ObservableCollection<PlateCategory>() {
                new PlateCategory{Name="手机"},
                new PlateCategory{Name="电脑"},
                new PlateCategory{Name="手表"},
            };
            Plates = new ObservableCollection<Plate>() {
                new Plate("WP",PlateCategories[0]),
                new Plate("IOS",PlateCategories[0]),
                new Plate("Android",PlateCategories[0])
            };
        }

        public static void AddPlate(Plate plate) {
            PlateRepo.Add(plate);
        }


        public static void AddPlateCategory(PlateCategory plateCategory) {
            PlateCateRepo.Add(plateCategory);
        }

        public static bool RemovePlate(Plate plate) {
            return PlateRepo.Remove(plate);
        }

        public static bool RemovePlateCategory(PlateCategory category) {
            return PlateCateRepo.Remove(category);
        }

        public static bool RemovePlate(int fid) {
            return PlateRepo.Remove(fid);
        }

        public static bool RemovePlateCategory(int id) {
            return PlateCateRepo.Remove(id);
        }

        private static IRepository<Plate> PlateRepo;
        private static IRepository<PlateCategory> PlateCateRepo;

}

看起来是不是一切over,但当我运行代码时,神奇的一幕出现了,抛出了一个TypeInitializationException异常,于是我找了很久错误,依然不知道什么原因,最后我翻开Jeff大神的CLR via C#,找到了静态构造方法的相关描述。

静态构造器会在第一次被调用时执行,也就是我调用Manager类时,Manager的静态方法开始执行,即初始化数据Plates集合和PlateCategories集合。执行这个任务时,静态构造器会调用一个线程和锁来确保数据不可被其他线程写,但这时,Plate和PlateCategory的构造器却调用了Manager类的Add方法,然而,Manager类是被锁起来的!因为他还没有被初始化完毕,所以就导致CLR抛出了一个异常,程序终止。5555~

然而,我为什么还要把仓库类给帮出来呢?好像并没有这个类什么事情,但其实并不是这样的。其实这个死并没有这么简单就作完。不过要表达的东西说完了,就不讲下去了,我才不会告诉你其实我一开始是在仓库中初始化数据呢╮( ̄▽ ̄)╭

技术分享

献上哥特萝莉sama照片一张。。。

类型构造器-记一次悲惨经历,论我是如何用静态构造器来作死的

标签:

原文地址:http://www.cnblogs.com/blackerXHunter/p/4536892.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!