魔术拆穿了,其实很简单

 

最近微软团队碰到一个不大不小的难题,搞了1个月也没解决掉,最后甚至打算提交给上海微软开Case来解决。

问题症结是:微软团队为我们开发一个StandardControl控件,组合了多个控件和组件,包括第三方的DevExpress,然而,当在工程的窗体中拖进StandardControl、编辑窗体控件属性、重新打开窗体,然后在调试(按F5)状态下,程序运行的好好,但IDE中这个窗体却不见了,而当退回到设计状态时,IDE甚至报错:“设计器加载程序未提供根组件,但没有指出原因。”由于IDE没有提供更多的提示,再加上有时报错是DevExpress控件报出的,所以怀疑是第三方控件造成的问题,还得我们帮忙来解决。
其实魔术拆穿了,很简单。
遮挡微软团队视角的有这几个方面:
1,认为.NET、IDE会自动控制资源的释放:这是一入道就玩.NET的人常犯的错误,如果是从C、Pascal等语言训练过来的人,对资源的加载和释放都是非常敏感的,特别是释放资源的事情。
2,不清楚特殊条件下如何调试代码:IDE不是万能的,一旦不允许对代码进行单步调试的时候怎么办,其实很简单,在需要设断点而无法调试到的代码前后,可以加上MessageBox()、或者写日志,总之,只要是能执行的代码,都是可以跟踪到的。
那么,只要具备应付这两问题的编程素质,所谓的难题自然不会困扰他很久。

我们通过在代码中设置MessageBox(),搞清楚IDE在构建、释放user control的时候都做了些什么动作,得出一个结论:IDE在释放资源的时候,并未按照设计者的思路行事。原因是user control中加入的组件BarManager与StandardControl有着指针的关联,一定的IDE环境下,IDE的资源释放顺序发生错乱,而最终导致IDE都无法分辨的莫名其妙故障。

那么到此,解决方法就很简单了,干预IDE的资源释放顺序就可以了。
以下是摘录的代码段,供设计.NET的组合控件时参考。

  1.   public class StandardControlDesigner : ControlDesigner
  2.   {
  3.     public StandardControlDesigner() { }
  4.     private StandardControl ContextControl
  5.     {
  6.       get { return this.Control as StandardControl; }
  7.     }
  8.     private IComponentChangeService _changeService;
  9.     private BarManager _barManager;
  10.     public override void Initialize(IComponent component)
  11.     {
  12.       base.Initialize(component);
  13.       if (_changeService == null)
  14.       {
  15.         _changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
  16.         if (_changeService != null)
  17.           _changeService.ComponentRemoving += new ComponentEventHandler(OnComponentRemoving);
  18.       }
  19.     }
  20.     public override void InitializeNewComponent(IDictionary defaultValues)
  21.     {
  22.       base.InitializeNewComponent(defaultValues);
  23.       CreateMenu();
  24.     }
  25.     protected override void Dispose(bool disposing)
  26.     {
  27.       if (disposing)
  28.       {
  29.         ClearContainer();
  30.         if (_barManager != null)
  31.           _barManager.Dispose();
  32.       }
  33.       base.Dispose(disposing);
  34.     }
  35.     private void OnComponentRemoving(object sender, ComponentEventArgs e)
  36.     {
  37.       if (ContextControl == e.Component)
  38.         ClearContainer();
  39.       else if (_barManager == e.Component)
  40.         _barManager = null;
  41.     }
  42.     private void ClearContainer()
  43.     {
  44.       if (ContextControl.Container != null)
  45.         foreach (Component item in ContextControl.Container.Components)
  46.         {
  47.           BarManager temp = item as BarManager;
  48.           if (temp != null)
  49.             if (temp.Form == ContextControl)
  50.             {
  51.               if (_barManager == temp)
  52.                 _barManager = null;
  53.               _changeService.ComponentRemoving -= new ComponentEventHandler(OnComponentRemoving);
  54.               try
  55.               {
  56.                 temp.Dispose();
  57.               }
  58.               finally
  59.               {
  60.                 _changeService.ComponentRemoving += new ComponentEventHandler(OnComponentRemoving);
  61.               }
  62.               break;
  63.             }
  64.         }
  65.     }
  66.     private void CreateMenu()
  67.     {
  68.       IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
  69.       if (host == null)
  70.         return;
  71.       if (_barManager != null)
  72.         _barManager.Dispose();
  73.       _barManager = new BarManager(ContextControl.Container);
  74.       _barManager.Form = ContextControl;
  75.       
  76.       ...
  77.    }
  78.   }
  79. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值