.net组件程序设计文摘

.net组件程序设计

第一章             面向组件编程简介

一个组件是一个.net

一个对象是一个组件的实例

面向对象编程着眼于被组合到一个大的二进制可执行程序的类之间的关系

面向组件编程着眼于独立工作的可替换的代码模块,并且无须非常熟悉其内部工作原理

 

优势:

简化软件项目管理

任何对组件的改进,增强,修复都能够马上提供给所有使用组件的应用程序

应用程序更加容易扩展

 

继承和重用模型上的着重点不同

面向对象白盒重用

面向组件黑盒重用

 

面向组件编程的原则

接口和实现分离应用程序中的基础单元是二进制兼容接口

二进制兼容性客户端和服务端之间

语言独立性编程语言的选择无关

位置透明客户端代码中没有任何有关对象执行的具体位置

分布式场景部署

并发管理

版本控制

基于组件的安全

 

第二章             .net 面向组件的编程要素

语言独立性

中间语言和JIT编译器

IL被封装在DLLEXE

JIT即时编译器处理把IL转变成真正的机器代码

 

两类用户:

1. 快速应用程序开发人员 VB

2. 企业应用开发人员 C#

 

EXE程序集应用程序集

DLL程序集库程序集

一个类可以有两种特性

累积特性是指一个类中的每个部分都可以添加的东西

非累积特性是指类型中的所有部分必须一致的东西

 

.net二进制兼容性

使用元数据提供这些方法或者字段的所有类型,都是二进制兼容的,因为该类型在内存中实际上的是二进制布局.

 

第三章             基于接口编程

一个接口不能包含任何实现,接口的所有方法和属性都是抽象的

一个接口不能被实例化,接口等同于一个抽象类

 

接口和抽象类的区别

1.      一个抽象类仍然可以有实现,它能够有成员变量或非抽象方法或属性,接口不能有实现或成员变量

2.      一个.net类只能从一个基类中派生,即便基类是抽象的,然而,一个.net类可以实现多个接口

3.      抽象类可以从其他类或从一个或多个接口中派生,而接口只能从另一接口中派生

4.      抽象类能够有非公共方法和属性,即便它们都是抽象的。接口所有的都是公共的

5.      抽象类可以有静态方法和静态成员,能定义常量,而接口不能有

6.      抽象类可以有构造函数,接口不可以

 

显式类型转换:

1.      非范型类工厂

2.      当你希望使用某个类实现的一个接口去获取该类实现的另外一个接口的引用

隐式类型转换:

防御性编程:

IMyInterface obj1;

IMyOtherInterface obj2;

obj1 =new MyClass();

obj1.Method1();

obj2 = obj1as IMyOtherInterface;

if (obj2 !=null)

{

  obj2.Method3();

}

接口同样可以定义属性,索引器,和事件

 

结构实现一个或多个接口

局部类型为一个类定义接口派生,其他类实现

一个接口成员只能由一个部分来实现

 

类从基类和接口派生时 基类放在第一位

 

显示实现接口并实现从一个接口引导到另一个

voidIMyOtherInterface.Method1()

{

  IMyInterface myInterface = this;

  myInterface.Method1();

}

使用 this引用的方式是通过它自己的实现类来调用显示接口方法的唯一途径

 

让实现范型类型的类来添加约束,而接口自身保持无约束

 

范型接口方法只对方法有效,属性和索引器只能在接口定义中使用范型参数

 

设计和分解接口

最理想的接口成员3-5

接口方法:属性 = 21

避免将定义事件作为接口成员

 

 

第四章             生命周期管理

托管堆在每个.net的宿主物理进程中,.net运行时都会预先分配一个叫做托管堆的特殊内存堆

通过压缩托管堆并用可到达对象覆盖不可带大对象来实现

   public class MyClass

   {

       public MyClass()

       {

       }

       ~MyClass()

       {

 

       }

}

确定性终结:

/闭模式 close()

处理Dispose()模式 dispose()

IDisposable()模式

 publicinterface IMyInterface{

   void SomeMethod();}

publicclass MyClass :IMyInterface, IDisposable{

   public void SomeMethod(){}

   public void Dispose(){}

 }

IMyInterface obj =new MyClass();

obj.SomeMethod();

IDisposable disposable = objas IDisposable;

if (obj !=null){

   disposable.Dispose();

}

   

 

using (obj){

  obj.SomeMethod();

}

 

接口和using语句相结合

1.  public interfaceIMyInterface :IDisposable

   {

       void SomeMethod();

}

2.  using ((IDisposable)obj)

           {

               obj.SomeMethod();

           }

3.   using (obj asIDisposable)

           {

               obj.SomeMethod();

           }

 

第五章             版本控制

兼容性规则:对于强名称程序集,兼容程序集必须具有客户端清单所请求的版本号。对于友好程序集,具有友好名的任何程序集都被认为是兼容的

Assembly assembly =Assembly.GetExecutingAssembly();

Version version = assembly.GetName().Version;

Trace.WriteLine("Version is " + version);

 

程序集部署模式:

专用安装在应用程序目录

共享安装在全局程序集缓存(GAC)的公共位置

1.      支持并行执行相同程序集的不同版本

2.      多个客户端应用程序之间共享程序集

 

第六章             事件

委托推断

当添加或删除目标方法时,编译器可以推断委托类型进行实例化。先不将方法名包装在委托对象中,而直接将方法名指定在委托变量中.

publicdelegate void NumberChangedEventHandler(int number);

publicclass MyPublisher{

   public NumberChangedEventHandler NumberChanged;}

   public classMySubscriber{

       public void OnNumberChanged(int number){

           string message = "New value is " + number;

           MessageBox.Show(message, "MySubscriber");}}

MyPublisher publisher =new MyPublisher();

MySubscriber subscriber1 =new MySubscriber();

 MySubscriber subscriber2 =new MySubscriber();

 publisher.NumberChanged += subscriber1.OnNumberChanged;

 publisher.NumberChanged +=new NumberChangedEventHandler(subscriber2.OnNumberChanged);

 publisher.NumberChanged(3);

 publisher.NumberChanged -=new NumberChangedEventHandler(subscriber2.OnNumberChanged);

event仅有发布类可以触发事件

publicdelegate void NumberChangedEventHandler(object sender,EventArgs eventArgs);

publicclass NumberChangedEventArgs :EventArgs{

   int m_Number;

   public NumberChangedEventArgs(int number){

        m_Number = number;}

   public int Number{

       get { return m_Number; }

   }

}

publicclass MyPublisher{

   public eventNumberChangedEventHandler NumberChanged;

   public void FireNewNumberEvent(EventArgs eventArgs){

       try{

           if (NumberChanged != null){

               NumberChanged(this, eventArgs);

           }}

           catch { }}

   }

publicclass MySubscriber{

   public void OnNumberChanged(object sender,EventArgs eventArgs){

           NumberChangedEventArgs numberArg = eventArgsas NumberChangedEventArgs;

           Debug.Assert(numberArg != null);

           string message = numberArg.Number.ToString();

           MessageBox.Show("The new number is " + message);

       }

}

 

MyPublisher publisher =new MyPublisher();

MySubscriber subscriber =new MySubscriber();

publisher.NumberChanged += subscriber.OnNumberChanged;

NumberChangedEventArgs numberArg =new NumberChangedEventArgs(4);

publisher.FireNewNumberEvent(numberArg);

范型事件

publicdelegate void GenericEventHandler<T,U>(T t,U u);

publicclass MyArgs :EventArgs { }

publicclass MyPublisher{

       public eventGenericEventHandler<MyPublisher,MyArgs> MyEvent;

       public void FireEvent(){

           MyArgs args =new MyArgs();

           MyEvent(this,args);

       }

   }

 publicclass MySubscriber<A>where A : EventArgs{

     public void OnEvent(MyPublisher sender, A args) { }

 }

 

 MyPublisher publisher =new MyPublisher();

 MySubscriber<MyArgs> subscriber = new MySubscriber<MyArgs>();

 publisher.MyEvent += subscriber.OnEvent;

 

使用别名

usingMyHandler = GenericEventHandler<MyPublisher,MyArgs>;

publicevent MyHandler MyEvent;

 

类型安全的EventsHelper

usingMyEventHandler = GenericEventHandler<int,string>;

publicdelegate void GenericEventHandler();

publicdelegate void GenericEventHandler<T,U>(T t,U u);

publicclass MyPublisher{

   public eventMyEventHandler MyEvent;

   public void FireEvent(int number,string str){

        EventsHelper.Fire(MyEvent,number,str);

   } 

}

publicstatic class EventsHelper{

    public static void UnsafeFire(Delegate del,paramsobject[] args){

       if (del == null){

           return;

       }

       Delegate[] delegates = del.GetInvocationList();

       foreach (Delegate sinkin delegates){

         try{

             sink.DynamicInvoke(args);

         }

        catch { }

        }

       }

       public staticvoid Fire<T,U>(GenericEventHandler<T,U> del,T t,U u)

       {

           UnsafeFire(del,t,u);

       }

       public static void Fire<T>(GenericEventHandler<T> del, T t)

       {

           UnsafeFire(del, t);

       }

}

事件访问器

usingMyEventHandler = GenericEventHandler<string>;

publicdelegate void GenericEventHandler();

publicdelegate void GenericEventHandler<T>(T t);

publicdelegate void GenericEventHandler<T,U>(T t,U u);

publicclass MyPublisher{

   MyEventHandler m_MyEvent;

   public eventMyEventHandler MyEvent{

         add { m_MyEvent += value; }

         remove { m_MyEvent -= value; }

   }

   public void FireEvent(){

         EventsHelper.Fire(m_MyEvent,"Hello");

   }

 }

 publicclass MySubscriber{

    public void OnEvent(string message){

         MessageBox.Show(message);

    }

 }

 

MyPublisher publisher =new MyPublisher();

MySubscriber subscriber =new MySubscriber();

publisher.MyEvent += subscriber.OnEvent;

publisher.FireEvent();

publisher.MyEvent -= subscriber.OnEvent;

 

第七章             异步调用

对象在后台执行方法调用后,控制权立即返回客户端,随后能以某种方式通知客户端该方法已经执行完毕

 

面向组件的异步调用机制必备条件

1.      即可以用于同步也可以用于异步

2.      由客户端来决定是同步还是异步

3.      客户端能够发起多个异步调用

4.      组件能够服务于多个并发调用

5.      组件的方法有输出参数或是返回值,客户端应该有办法在方法结束时获取他们

6.      发生在组件端的错误能反馈到客户端

7.      异步调用机制方便使用

客户端执行一个异步方法后有以下选择

1.      阻塞直到调用完成

2.      等待方法调用完成

3.      等待一段时间,停止等待

4.      同时等待多个方法的完成

5.      回调函数

publicdelegate int BinaryOperation(int argument1, int argument2);

   public classCalculator

   {

       public int Add(int argument1,int argument2)

       {

           return argument1 + argument2;

       }

       public int Subtract(int argument1,int argument2)

       {

           return argument1 - argument2;

       }

}

 

 

Calculator calculator =new Calculator();

BinaryOperation oppDel = calculator.Add;

 //oppDel(2,3);

 //oppDel.Invoke(2,3);

IAsyncResult asyncResult = oppDel.BeginInvoke(2,3,null,null);

int result = oppDel.EndInvoke(asyncResult);

EndInvoke()在每次异步操作时只能调用一次。

委托类的内部列表中只能允许有一个目标方法

只能在分发调用的那个委托对象上把IAsyncResult对象传递给EndInvoke()

publicclass CalculatorClient

   {

       IAsyncResult m_AsyncResult;

       public void AscuncAdd()

       {

           Calculator calculator = new Calculator();

           DispatchAdd(calculator,2,3);

           int result = GetResult();

       }

 

       int GetResult()

       {

           AsyncResult asyncResult = (AsyncResult)m_AsyncResult;

           BinaryOperation oppDel = (BinaryOperation)asyncResult.AsyncDelegate;

           Debug.Assert(asyncResult.EndInvokeCalled ==false);

           return oppDel.EndInvoke(m_AsyncResult);

       }

       void DispatchAdd(Calculator calculator,int argument1, int argument2)

       {

           BinaryOperation oppDel = calculator.Add;

           m_AsyncResult = oppDel.BeginInvoke(argument1, argument2, null, null);

       }

}

 

阻塞

IAsyncResult asyncResult = oppDel.BeginInvoke(2,3,null,null);

           while (asyncResult.IsCompleted == false)

           {

               asyncResult.AsyncWaitHandle.WaitOne(10,false);

           }

           int result = oppDel.EndInvoke(asyncResult);

 

        BinaryOperation oppDel1 = calculator.Add;

           BinaryOperation oppDel2 = calculator.Add;

           IAsyncResult asyncResult1 = oppDel1.BeginInvoke(2, 3,null, null);

           IAsyncResult asyncResult2 = oppDel2.BeginInvoke(2, 3,null, null);

           WaitHandle[] handleArray = { asyncResult1 .AsyncWaitHandle,asyncResult2.AsyncWaitHandle};

           WaitHandle.WaitAll(handleArray);

 

回调方法

publicclass CalculatorClient

   {

       public void AscuncAdd()

       {

           Calculator calculator = new Calculator();

           BinaryOperation oppDel = calculator.Add;

           oppDel.BeginInvoke(2,3,OnMethodCompletion,null);

       }

       void OnMethodCompletion(IAsyncResult asyncResult)

       {

           int result = 0;

           AsyncResult resultObj = (AsyncResult)asyncResult;

           Debug.Assert(resultObj.EndInvokeCalled ==false);

           BinaryOperation oppDel = (BinaryOperation)resultObj.AsyncDelegate;

           result = oppDel.EndInvoke(asyncResult);

           Trace.WriteLine("aa" + result);

       }

}

参数传递

int asyncsState = 4;

oppDel.BeginInvoke(2, 3, OnMethodCompletion, asyncsState);

int ret = (int)asyncResult.AsyncState;

异步流

异步web

异步错误处理

 try

 {

      result = oppDel.EndInvoke(asyncResult);

      Trace.WriteLine("aa" + result);

 }

 catch { }

异步事件

 

异步调用的缺陷:

1.   线程并发与同步

2.     线程池的消耗

3.     对引用和引用类型的过早访问

4.     费时的构造函数

5.     EndInvoke()后的清理

 

 

第八章 多线程和并发管理

一个线程仅仅是一个进程中的一条执行路径

面向cpu的操作用计算机的中央处理器进行密集的或重复的操作

面向I/O的操作是使用输入或输出设备

 

创建线程

publicclass MyClass

   {

       public void ShowMessage()

       {

           Thread currentThread = Thread.CurrentThread;

           string caption = "Thread ID = ";

           caption += currentThread.ManagedThreadId;

           MessageBox.Show(caption);

       }

}

MyClass obj =new MyClass();

//ThreadStart threadStart = obj.ShowMessage;

//Thread workerThread = new Thread(threadStart);

Thread workerThread =new Thread(obj.ShowMessage);

workerThread.Start();

Thread.Sleep(0);强制上下文切换

 

自动同步

如果一组面向上下文的对象共有一把锁,就说他们在一个同步域中

一个对象可以处于以下任何一个同步域中:

1.在它创建者的同步域中(该对象和它的创建者共享一把锁)

2.在新的同步域中(对象有自己的锁并启动一个新的同步域)

3.完全不在同步域中(因为没有锁,并发访问是允许的)

SynchronizationAttribute.REQUIRED创建者同步域

SynchronizationAttribute.REQUIRES_NEW新同步域  类工厂应用

 

同步域的缺陷:

1.   只能在面向上下问的对象上使用,对于.net的其他类型,仍然手动同步

2.   以代理和拦截器的方式访问面向上下文的对象要付出一定的代价

3.   不能保护静态类成员和静态方法

4.   不是一个面向吞吐量的机制

 

手动同步

 

监视器

只和引用类型一块工作的锁

MyClass obj;

Monitor.Enter(obj);

Try

{

obj.ShowMessage();

}

Finnaly

{

Monitor.Exit(obj);

}

保护静态成员和方法

publicclass MyClass

{

   static publicvoid ShowMessage()

   {

   }

}

Monitor.Enter(typeof(MyClass));

MyClass.ShowMessage();

Monitor.Exit(typeof(MyClass));

 

MyClass obj;

lock (obj){obj.ShowMessage();}

publicclass MyClass

{

   public void ShowMessage()

   {

        lock (this)

        {

        }

    }

}

 

属性不需要加临时变量

   public classMyClass

   {

       int m_Number;

       public int Number

       {

           get

           {

               lock(this)

               {

                   return m_Number;

               }

           }

       }

}

 

同步方法

[MethodImpl(MethodImplOptions.Synchronized)]

       public void DoSomething()

       {

 

       }

 

可等待句柄

Monitor的区别:

Monitor只能在引用类型上使用

可等待句柄同步对值类和引用类型进行访问

可等待句柄多个对象等待是一个原子操作

 

互斥

命名Mutex过去产物

一个命名Mutex的技巧:

不一定要同步对系统范围资源的访问,而是简单易用的跨进程通信机制,为单例应用程序提供了方便

可等待事件

Monitor区别:

Monitor受到束缚后没有该动作的任何记忆

事件有记忆,状态保存在信号已发上信号

Mutex也叫 二进制 Semaphores

以某种可计算的方式控制线程的执行互锁

只是增加减少数值或交换比较数值

支持一系列以原子方式访问变量的静态方法

Mutex m = new Mutex();

m.WaitOne();

m.ReleaseMutex();


/写锁

使用Monitor对象锁定整个对象的效率很差,一个宏观的锁会锁定所有对象

使用Mutex效率也很差,如果没有线程写入新数值,多个线程就可以并发的读取当前数据

一个成员变量或属性。经常被多线程读写

ReadWriterLock m = new ReadWriterLock();

m.AcquireWriterLock(Timeout.Infinite);

m.ReleaseWriterLock();

 

同步委托

  public eventEventHandler MyEvent;

       public void FireEvent()

       {

           FireEvent();

       }

       [MethodImpl(MethodImplOptions.NoInlining)]

       void FireEvent(EventHandler handler)

       {

           if(handler != null)

           {

               handler(this,EventArgs.Empty);

           }

       }

 

使用.net多线程服务

线程相关静态变量

 

线程本地存储

命名内存槽

未命名内存槽

 

线程池

工作线程用于处理异步执行或计时器 25

完成端口线程是用来与服务器操作联合的 1000

 

计时器

 

第九章 序列化和持久化

序列化当应用程序关闭时,对象状态被保存在文件中

反序列化应用程序启动时加载一些包含数据的文件,并将文件中的信息转化为对象

 

自动序列化 .net通过反射实现对象的自动序列化每个.net类型的状态大批能够通过反射来读取或设置 .net把对象状态序列化为流

 

.net序列化是基于对象的只有实例字段被序列化静态字段不行

枚举永远是可序列化的

 

[Serializable]

publicclass MyClass

[NonSerialized]

.net反序列化时,它会将每个不可序列化成员变量初始化为该类型的默认值

[Serializable]

   public classMyClass :IDeserializationCallback

   {

       [NonSerialized]

       IDbConnection m_Connection;

       string m_ConnectionString;

 

       public void OnDeserialization(object sender)

       {

           m_Connection = newSqlConnection();

           m_Connection.ConnectionString = m_ConnectionString;

           m_Connection.Open();

       }

}

 

所有委托定义可序列化类

.net带有两个格式器

二进制格式器和soap格式器

 

自定义序列化

 

 

第十章 远程处理

内部网环境下.net remoting

Internet web服务

 

在托管代码和非托管代码之间的桥梁

应用程序域是建立在非托管进程上的

同一进程的所有应用程序域共享同一托管堆

 

.net把包含服务器对象的应用程序域称为宿主应用程序域

 

值传递 引用传递

引用封送激活模式 客户端激活和服务器激活

客户端激活对象

服务端single-call

服务端singleton

 

客户端代理  透明代理  真实代理

 

当使用http作为传输协议时,可以选择用SOAP来穿过防火墙

 

三种协议:

1.   tcp

2.     http

3.     ipc 只能在同一机器的跨进程调用使用

 

编程式和管理式

 

第十一章 上下文与拦截

拦截:拦截从客户端到对象的调用,执行某些调用前处理,将调用转发给对象,执行某些调用后处理,然后将控制返回给客户端

 

上下文敏捷对象

面向上下文对象

 

组件服务类型

面向上下文服务和企业服务

 

第十二章 安全

附录A基于接口的Web服务

附录B统一windows forms asp.net安全

附录C反射与属性

附录D范型

附录E c#编码准则

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值