Flikas 的个人资料Flikas' Space照片日志列表更多 工具 帮助

日志


    1月29日

    XML Web Service学习笔记 1 .NET框架基础

    一、了解.NET

    通过XML Web服务,.NET解决了软件业的一个最大难题:在以不同语言、为不同环境编写的应用程序之间交换数据。.NET能够创建多种平台下的应用程序,并通过标准协议(HTTP,XML,SOAP等)允许它们交换数据。

    .NET提供的工具及操作系统包括:

    • 智能客户端软件:允许客户端、PC或移动设备利用XML Web服务从任何设备和位置访问数据。
    • .NET Server基础结构:Windows 2000 Server、Windows .NET Server 以及 .NET Enterprise Server
    • XML Web服务:.NET环境下应用程序集成的核心。
    • Visual Studio .NET和.NET框架:创建工具。

    二、自动内存管理

    自动内存管理运作方式:初始化一个进程时,运行库会预留一个连续的地址空间,但不为其分配任何存储空间。这一段预留的地址称为托管堆。当使用new运算符初始化对象时,才使用托管堆中的地址分配存储空间。分配和垃圾回收机制保证了分配的地址空间总是连续的,这样的话,在托管堆中为对象分配内存所需的时间比分配非托管内存的时间短,非托管内存指针是以链表方式存储的,每次分配都需要遍历链表找到较大的内存块以容纳对象。

    释放内存:每个应用程序都有一组根,指向托管堆上的对象,这些跟包括了所有应用程序当前使用的对象,JIT编译器和运行库维护应用程序根的列表。垃圾回收器使用这一根的列表来创建托管堆上对象的图表,所有从根开始直接或间接被引用到的对象标记为可访问的,而其他对象被视为垃圾应当回收。这些垃圾对象所占用的内存被回收以后,托管堆上的地址将不再连续,这时垃圾回收器执行内存复制功能来压缩托管堆中的对象(只是改变对象的地址,所以并不太耗时间),并更新根的列表使应用程序的根正确的指向先前所指的对象。

    为了更优化垃圾回收的效率,垃圾回收器将托管堆上的对象分为0、1、2三代,0代包含最近创建的对象,每次垃圾回收,优先回收第0代对象,并将幸存的对象提升一代,只有当第0代对象回收所释放的空间不足时,才回收更高代的对象。

    垃圾回收器回收对象之前,都会调用对象的Finalize方法以期释放对象使用的非托管资源,如文件指针或网络连接等。另一种确保非托管资源被正确回收的方法是在Dispose方法中提供清除代码,并在完成对象后显式的调用它。

    实现终结程序:Dispose和Finalize方法叫做终结程序。Finalize方法会在垃圾回收时被自动调用,Dispose方法不会。如果实现了Dispose方法,那么可以在Finalize方法中调用Dispose方法,这时,Dispose方法应当只释放非托管资源,这是由于在终结过程中,垃圾回收器可能已经删除了Dispose方法欲处理的那个对象,这将导致Dispose方法失败。而如果Dispose方法是被显式调用的,那么Dispose方法应当释放所有托管及非托管资源。最后,Dispose方法应当调用GC.SuppressFinalize方法,阻止对Finalize方法的调用,并阻止重复调用Dispose方法。

    .NET框架提供了IDisposable接口来为那些实现了Dispose方法的类提供统一的类型。

    下面是一个Dispose和Finalize方法的例子:

    public class Parent:IDisposable
    {
        private IntPtr ptr;                              //非托管资源
        private System.Timers.Timer timer;       //托管资源
        private bool disposed;                        //这个变量用于防止Dispose方法被多次调用

        public void Dispose()                          //这个方法被用户显式调用
        {
             Dispose(true);
             GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool called_by_user)     //这个保护(protected)方法会被Finalize方法调用
        {
            if(!this.disposed)
            {
                 if(called_by_user)
                 {
                      //清除托管资源
                      timer.Dispose();
                 }
                 //清除非托管资源
                 ptr=IntPtr.Zero;
                 disposed=true;
            }
        }

        ~Parent()                    //Finalize方法
        {
             Dispose(false);
        }
    }

    public class Child:Parent
    {
         .
         .
         .
         protected override void Dispose(bool called_by_user)
         {
               //Child对象的清除代码:
               .
               .
               .
               //调用父对象的清除代码:
               base.Dispose(called_by_user);
         }
    }

    三、程序集

    通常使用Visual Studio.NET创建的可移植的可执行文件(.exe或.dll)都是静态程序集。另外,借助System.Reflection.Emit命名空间下的反射API,可以创建动态程序集。反射API允许程序在运行时通过发送元数据和MSIL代码来实时创建程序集,并根据情况在磁盘上将其保存为可移植的可执行文件。

    程序集既可以是单文件的,也可以是多文件的。单文件程序集包含程序集清单,类型元数据,MSIL代码和资源。多文件程序集将单文件程序集的内容拆成几个部分,并由单独的程序集清单将它们连接在一起,这样可以将很少使用的类型存储在单独的文件中,当需要时再下载。程序集链接器工具——AL.exe,用于通过组合一个或多个模块和资源文件来创建单独的清单文件。

    程序集还可以分为私有程序集和共享程序集。私有程序集只可为该应用程序访问。共享程序集具有强名称,安装在GAC中,可由多个程序共享。强名称包含程序集名称、版本、区域信息、数字签名以及公钥信息。

    要使应用程序具有强名称,就必须为它提供一个密钥对,并在程序集的AssemblyKeyFile属性中指定密钥对文件名称。如下:

    using System.Reflection;
    [assembly:AssemblyKeyFile("MyKey.dat")]

    可以使用强名称工具SN.exe创建密钥对,另外,sn.exe还可以实现验证,创建密钥对和为程序集签名。

    为程序集分配强名称以后,就可以使用GAC工具——GACUtil.exe将程序集安装到GAC中了。

    四、一些实验

    1.使用Visual Basic.NET 创建一个模块:

    namespace Util
         public class HelloUtil
              public shared sub Hello()
                   System.Console.WriteLine("Hello, how are you doing!")
              end sub
         end class
    end namespace

    将以上代码写入文本文件,命名为HelloUtil.vb,然后编译该模块:

    vbs /t:module HelloUtil.vb

    编译成功,将生成HelloUtil.netmodule文件。

    2.使用JScript创建一个模块:

    import System;
    package Util
    {
         public class GoodByeUtil
         {
               public static function GoodBye()
               {
                      Console.WriteLine("Goodbye, see you next time!");
               }
         }
    }

    将以上的代码写入文本文件,命名为GoodbyeUtil.js,编译:

    jsc /t:library GoodbyeUtil.js

    注意:编译成功后,将生成GoodbyeUtil.dll文件,不能将JScript代码编译至模块中。

    3.使用C#创建Main模块:

    using System;
    using Util;           //前两个模块使用的命名空间,这两个模块使用的是同一个命名空间

    class MyClass
    {
         [STAThread]
         public static void Main(string[] args)
         {
               Console.WriteLine("Hello from Main.");
               HelloUtil.Hello();
               GoodByeUtil.GoodBye();
         }
    }

    将以上代码保存为文本文件,命名为Main.cs,使用csc.exe编译以上代码。由于引用了其他模块,这次的命令比较复杂:

    csc /addmodule:HelloUtil.netmodule /r:GoodByeUtil.dll, Microsoft.Jscript.dll /target:module Main.cs

    编译生成Main.netmodule文件,如果把上面的/target:module改成/target:exe,就可以编译生成可执行文件Main.exe,但是这个可执行文件需要HelloUtil.netmodule以及GoodByeUtil.dll这两个文件才能执行,如果想要生成单一文件,就需要使用程序集链接器——Al.exe:

    al /t:exe /out:MyApp.exe /main:MyClass.Main HelloUtil.netmodule GoodByeUtil.dll Main.netmodule

    生成的MyApp.exe就是将以上文件组合而成的单独的程序集。

    链接时会出现警告AL1020,原因是从GoodByeUtil.dll创建了程序集,而GoodbyeUtil.dll本身也是一个程序集,程序集链接器将忽略它。

    评论

    请稍候...
    很抱歉,您输入的评论太长。请缩短您的评论。
    您没有输入任何内容,请重试。
    很抱歉,我们当前无法添加您的评论。请稍后重试。
    若要添加评论,需要您的家长授予您相应权限。请求权限
    您的家长禁用了评论功能。
    很抱歉,我们当前无法删除您的评论。请稍后重试。
    您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
    因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
    完成下面的安全检查,您提供评论的过程才能完成。
    您在安全检查中键入的字符必须与图片或音频中的字符一致。

    若要添加评论,请使用您的 Windows Live ID 登录(如果您使用过 Hotmail、Messenger 或 Xbox LIVE,您就拥有 Windows Live ID)。登录


    还没有 Windows Live ID 吗?请注册

    引用通告

    此日志的引用通告 URL 是:
    http://flikas.spaces.live.com/blog/cns!FD1E577523FE041C!121.trak
    引用此项的网络日志