好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ESB相关技术入门

ESB相关技术入门

ESB ( Enterprise Service Bus )企业系统总线,主要是的作用是通过这个基础架构将企业内部的服务组织在一起,服务与服务之间可以相互进行调用,并且提供一种负载均衡机制。当然其中还是有了很多技术打算做成一个系列的文章,本次并没有打算直接讲解 ESB 整体的架构思想,而是将它进行了拆分,讲诉了其中一些使用的技术点。通过这些点的拆分,我们可以了解其中所使用的技术并进行自我充电,在后续我们将会介绍一下具体的架构思想。

       本期主要的技术点如下:

1.         FileSystemWatcher :文件侦听类。

2.         CodeDomProvider :创建和检索代码类。

3.         Appdomain :应用程序域。

4.         MarshalByRefObject :跨应用程序域边界访问对象。

 

1.       FileSystemWatcher

定义:侦听文件系统更改通知,并在目录或目录中的文件发生更改时引发事件。

具体实现:

        public void RegeditFileSystemWatcher( string filePath, string filter)

        {

            FileSystemWatcher watcher = new FileSystemWatcher (filePath);

            watcher.Created += FileSystemEventHandler;

            watcher.Changed += FileSystemEventHandler;

            watcher.Deleted += FileSystemEventHandler;

            watcher.EnableRaisingEvents = true ;

        }

 

        private void FileSystemEventHandler( object sender, FileSystemEventArgs e)

        {

            if (e.ChangeType == WatcherChangeTypes .Changed)

                Console .WriteLine( "Changed~~~~~~~~~~~~~" );

            else if (e.ChangeType == WatcherChangeTypes .Created)

                Console .WriteLine( "Created~~~~~~~~~~~~~" );

            else if (e.ChangeType == WatcherChangeTypes .Deleted)

                Console .WriteLine( "Deleted~~~~~~~~~~~~~" );

        }

总结:通过文件的变更,可以通知我们进行相应的处理,例如重新加载 dll 文件到 Appdomain 当中,而无需重启应用程序(此演示示例将在下文档中进行体现)。

 

2.       CodeDomProvider

定义: CodeDomProvider 可用于创建和检索代码生成器和代码编译器的实例。代码生成器可用于以特定的语言生成代码,而代码编译器可用于将代码编译为程序集。

A.       我们可以通过已经编写的固定代码来编译成固定的 dll 文件:

具体实现:

            IDictionary < string , string > version = new Dictionary < string , string >();

            if (System.Runtime.InteropServices. RuntimeEnvironment .GetSystemVersion().StartsWith( "v4.0" ))

                version.Add( "CompilerVersion" , "v4.0" );

            else

                version.Add( "CompilerVersion" , "v3.5" );

            CodeDomProvider provider = new CSharpCodeProvider (version);

            CompilerParameters parameters = new CompilerParameters ();

            parameters.GenerateInMemory = false ;

            parameters.OutputAssembly = assemblyFileName;

            parameters.ReferencedAssemblies.Add( "System.dll" );

            parameters.ReferencedAssemblies.Add( "MyInterface.dll" );

            CompilerResults clr = provider.CompileAssemblyFromSource(parameters, code);

            if (clr.Errors.HasErrors)

            {

                throw new Exception (code + clr.Errors);

            }

B.       我们也可以通过 CodeDOM 模型生成和编译源代码

具体实现:

     class CodeDomExample

    {

        // Build a Hello World program graph using

        // System.CodeDom types.

        public static CodeCompileUnit BuildHelloWorldGraph()

        {

            // Create a new CodeCompileUnit to contain

            // the program graph.

            CodeCompileUnit compileUnit = new CodeCompileUnit ();

 

            // Declare a new namespace called Samples.

            CodeNamespace samples = new CodeNamespace ( "Samples" );

            // Add the new namespace to the compile unit.

            compileUnit.Namespaces.Add(samples);

 

            // Add the new namespace import for the System namespace.

            samples.Imports.Add( new CodeNamespaceImport ( "System" ));

 

            // Declare a new type called Class1.

            CodeTypeDeclaration class1 = new CodeTypeDeclaration ( "Class1" );

            // Add the new type to the namespace type collection.

            samples.Types.Add(class1);

 

            // Declare a new code entry point method.

            CodeEntryPointMethod start = new CodeEntryPointMethod ();

 

            // Create a type reference for the System.Console class.

            CodeTypeReferenceExpression csSystemConsoleType = new CodeTypeReferenceExpression ( "System.Console" );

 

            // Build a Console.WriteLine statement.

            CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression (

                csSystemConsoleType, "WriteLine" ,

                new CodePrimitiveExpression ( "Hello World!" ));

 

            // Add the WriteLine call to the statement collection.

            start.Statements.Add(cs1);

 

            // Build another Console.WriteLine statement.

            CodeMethodInvokeExpression cs2 = new CodeMethodInvokeExpression (

                csSystemConsoleType, "WriteLine" ,

                new CodePrimitiveExpression ( "Press the Enter key to continue." ));

 

            // Add the WriteLine call to the statement collection.

            start.Statements.Add(cs2);

 

            // Build a call to System.Console.ReadLine.

            CodeMethodInvokeExpression csReadLine = new CodeMethodInvokeExpression (csSystemConsoleType, "ReadLine" );

 

            // Add the ReadLine statement.

            start.Statements.Add(csReadLine);

 

            // Add the code entry point method to

            // the Members collection of the type.

            class1.Members.Add(start);

 

            return compileUnit;

        }

 

        public static void GenerateCode( CodeDomProvider provider, CodeCompileUnit compileunit)

        {

            // Build the source file name with the appropriate

            // language extension.

            String sourceFile;

            if (provider.FileExtension[0] == '.' )

            {

                sourceFile = "TestGraph" + provider.FileExtension;

            }

            else

            {

                sourceFile = "TestGraph." + provider.FileExtension;

            }

 

            // Create an IndentedTextWriter, constructed with

            // a StreamWriter to the source file.

            IndentedTextWriter tw = new IndentedTextWriter ( new StreamWriter (sourceFile, false ), "     " );

            // Generate source code using the code generator.

            provider.GenerateCodeFromCompileUnit(compileunit, tw, new CodeGeneratorOptions ());

            // Close the output file.

             tw.Close();

        }

 

        public static CompilerResults CompileCode( CodeDomProvider provider, String sourceFile, String exeFile)

        {

            // Configure a CompilerParameters that links System.dll

            // and produces the specified executable file.

            String [] referenceAssemblies = { "System.dll" };

            CompilerParameters cp = new CompilerParameters (referenceAssemblies, exeFile, false );

            // Generate an executable rather than a DLL file.

            cp.GenerateExecutable = true ;

 

            // Invoke compilation.

            CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);

            // Return the results of compilation.

            return cr;

        }

    }

       总结:通过 CodeDomProvider 这种方式,我们可以动态的编译一些 dll ,并通过 Appdomain 加载这些 dll 文件来实现我们需要的服务,可以说这种实现方式的灵活性更高。更有利于我们动态的部署,其中 ESB 就采用这种方式来实现服务的插入。后续我们将介绍一下 Appdomain 。

 

3.       Appdomain

定义: Appdomain 提供应用程序卸载,隔离,安全边界,一个 Appdomain 可以被创建多个,可以在 Appdomain 当中加载相应的 dll 文件。如果 Appdomain 变的不可控的时候,我们可以卸载相应的 Appdomain 而不影响主进程。多个应用程序可以运行在一个进程当中,多个线程也可以同时属于一个应用程序域,但是在给定的时间一个线程只能在一个应用程序域中运行。

具体实现:

      AppDomainSetup appDomainSetup;

      appDomainSetup = new AppDomainSetup ();

      appDomainSetup.LoaderOptimization = LoaderOptimization .SingleDomain;

      appDomainSetup.ApplicationBase = AppDomain .CurrentDomain.BaseDirectory;

      appDomainSetup.ShadowCopyDirectories = appDomainSetup.ApplicationBase;

      appDomainSetup.ShadowCopyFiles = "false" ;

      AppDomain appDomain = AppDomain .CreateDomain(assemblyFileName, null , appDomainSetup);

总结: Appdomain 可以加载相应的 dll 文件,这样我们可以创建多个 Appdomain 并将这些 Appdomain 当做相应的服务, Appdomain 之间的加载、卸载之间不相互影响。 Appdomain 提供良好的应用程序的隔离, ESB 当中即使用这种方式将服务之间隔离开来。

 

4.       .net Remoting

定义: .net Remoting 一种分布式系统的处理方式,我们不打算研究它分布式的内容, .net Remoting 还有一种应用场景就是实现应用程序域之间的访问,我们可以跨一个应用程序域与另外的应用程序域进行通信,及穿越边界值。

具体实现:

RemoteLoader remoteLoader = ( RemoteLoader ) appDomain.CreateInstance( "Demo" , "Demo.RemoteLoader" ).Unwrap();

 

class RemoteLoader : MarshalByRefObject

    {

        public object Create( string assemblyFile, string typeName, object [] constructArgs)

        {

             

              // 略,详见示例代码

            return Activator .CreateInstance(matchType);

        }

    }

总结:通过 Appdomain 与 .net Remoting 的结合我们可以在某个 Appdomain 当中加载相应的 dll 并进行调取。使用 .net Remoting 核心是需要“调取类”或者是“处理类”必须继承自 MarshalByRefObject 。

 

代码如下:

源代码下载地址

资料如下:

http://msdn.microsoft.com/zh-cn/library/system.io.filesystemwatcher.aspx

http://msdn.microsoft.com/zh-cn/library/system.codedom.compiler.codedomprovider(VS.80).aspx

http://msdn.microsoft.com/zh-cn/library/system.appdomain(v=VS.80).aspx

http://msdn.microsoft.com/zh-cn/library/system.marshalbyrefobject(v=vs.80).aspx



http://www.cnblogs.com/assessment/archive/2011/08/22/2138538.html

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于ESB相关技术入门的详细内容...

  阅读:58次