上面一篇主要阐述了这个项目的实现目的和架构设计.下面开始是对其中的类的分析:
首先分析的是ImportManager类,可以看到客户端的代码访问的就是这个类.
我在ImportManager类中使用了外观模式,对客户端代码屏蔽了具体操作的代码.
这个类是一个singleton,具体的实现主要有下面这段代码:
2 /// The singleton instance to use with static methods.
3 /// </devdoc>
4 // see this post (http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx) on why we do this
5 internal static ImportManager Current
6 {
7 get
8 {
9 if (instance == null)
10 {
11 lock (syncObject)
12 {
13 if (instance == null)
14 {
15 instance = new ImportManager();
16 }
17 }
18 }
19 return instance;
20 }
21 }
相信,读过设计模式的朋友对上面这段代码都很熟悉吧.
Singleton模 式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程 序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。
从另一个角度来说,Singleton模式其实也是一种职责型模式。因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责!
这种方式的 实现对于线程来说是安全的。我们首先创建了一个进程辅助对象,线程在进入时先对辅助对象加锁然后再检测对象是否被创建,这样可以确保只有一个实例被创建, 因为在同一个时刻加了锁的那部分程序只有一个线程可以进入。这种情况下,对象实例由最先进入的那个线程创建,后来的线程在进入时(instence == null)为假,不会再去创建对象实例了。但是这种实现方式增加了额外的开销,损失了性能。
我在开发过程中还遇到一个问题.
在客户端如下使用ImportManager时:
2 {
3 ImportManager.EndReport +=new EndReportEventHandler(worker_EndWork );
4 ExecuteDelegate ed = new ExecuteDelegate( ExcelImportDB );
5 ed.BeginInvoke(ofd.FileName,null,null);
6 }
第一次使用一切正常,而第二次,第三次会发现对话框会弹出来多次的情况,而且第二次就会弹出来二次,第三次选择文件时会弹出来三次.
后来在调试过程中,发现是事件引起的.在到网上查了事件的文章,才知道原来事件在结束后,需要把它释放.以前由于使用的不是静态类,所以不会发生这种事情.但是这次使用了singleton模式,事件始终在内存中没有被释放,所以加了以下语句就解决了:
ImportManager.EndReport
-=new EndReportEventHandler(worker_EndWork );
后面是源代码:
2 {
3 private static volatile ImportManager instance;
4 private TranContext currentContext;
5 private static object syncObject = new object();
6 public static event EndReportEventHandler EndReport;
7 private ImportManager()
8 {
9 }
10 /// <devdoc>
11 /// The singleton instance to use with static methods.
12 /// </devdoc>
13 // see this post (http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx) on why we do this
14 internal static ImportManager Current
15 {
16 get
17 {
18 if (instance == null)
19 {
20 lock (syncObject)
21 {
22 if (instance == null)
23 {
24 instance = new ImportManager();
25 }
26 }
27 }
28 return instance;
29 }
30 }
31 public static void ExcelImportDB(string key,string askFileName,string operation)
32 {
50 ArgumentValidation.CheckForEmptyString (key,"key");
51 ArgumentValidation.CheckForEmptyString (askFileName,"askFileName");
52 ArgumentValidation.CheckForEmptyString (operation,"operation");
53 CreateContext(key,askFileName,operation);
54 Current.currentContext.Execute();
55 }
56 private TranContext createContext(string key,string askFileName,string operation)
57 {
58 return new TranContext (key,askFileName,operation);
59 }
60 private static void CreateContext(string key,string askFileName,string operation)
61 {
62 if (Current.currentContext ==null)
63 {
64 Current.currentContext=new TranContext (key,askFileName,operation);
65 Current.currentContext.EndReport +=new EndReportEventHandler(Current.OnEndReport);
66 }
67 }
68 private void OnEndReport(object sender,EndReportEventArgs e )
69 {
70 if (EndReport != null)
71 {
72 EndReport(this, e);
73 }
74 }
75 }