博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Visual Studio for Application 内幕之一(转载)

Posted on 2008-01-11 19:02  张冰  阅读(794)  评论(0编辑  收藏  举报

Visual Studio for Application 内幕之一

关于vsa 的文档资料非常少,这也是我决定写一些介绍些文字的目的。当然,这里只是我对vsa的一些理解,可能有错误的地方,同时,也可能不适合初学者。

由于内容很多,计划分多次介绍

  • 概述
  • 装入预编译代码
  • HostObject
  • Vsa IDE
  • Vsa sdk 部分(可能分多次)


在最前面的讲述中,我们不使用vsa sdk ,实际上,不用vsa sdk也可以实现所有的功能,在后面,我们详细介绍Vsa sdk(主要以beta 2为例,当然,我也打算介绍无意中发现的Vs.net 2003的vsa sdk版本)

相关命名空间

首先,我们来查看关于vsa的命名空间,发现有
Microsoft.Vsa(Microsoft.Vsa.Dll)
Microsoft.VisualBasic.Vsa(Microsoft.VisualBasic.Vsa.Dll)
Microsoft.JScript.Vsa(Microsoft.JScript.Vsa.Dll)
Microsoft_VsaVb(Microsoft_VsaVb.dll)

刚涉及vsa的开发者,很难理清其内在关系。我的理解是
vsa的功能实际上由基于com的实现完成,vsavbdt.dll是vsa设计时,而vsavb7rt.dll则是vsa运行时

Microsoft.Vsa 定义了基本的接口,枚举,异常
这里面重要的是VsaLoader类
VsaLoader主要用于装载和执行预先编译的vsa代码,只实现部分IVsaEngine接口,执行起来非常的快,在第二部分我们会介绍如何使用VsaLoader来装载预编译的Vsa代码

Microsoft_VsaVb是com实现的.net包装,查看Microsoft_VsaVB的代码,会发现其主要使用ComImportAttribute,Microsoft_VsaVB定义了VsaDTEngine接口(实现IVsaDTEngine接口),VsaDTEngineClass类(实现VsaDTEngine接口),VsaEngine接口(实现IVsaEngine接口),VsaEngineClass(实现VsaEngine接口)


而Visualbasic.Vsa和Microsoft.JScript.Vsa则分别是vb.net和JScript的具体实现

理解site 的概念

site相当于场所,VsaEgnine有IVsaSite的接口属性Site,其意义是我们需要创建一个实现IVsaSite接口的类,接受从VsaEngine引发的,如Notify,OnCompilerError,向实现IVsaEngine接口的对象提供值,如GetCompiledState,GetGlobalInstance等

IVsaSite非常重要,在以后我们会谈到
如:
读取预编译的代码
hostobject等


创建一个实现IVsaSite的类

imports Microsoft.vsa
class MyVsaSite
 implements IVsaSite
 .....

end class


任务场景:使用Microsoft.VisualBasic.vsa.VsaEngine 动态装入一个vb.net Class并运行

这是一个最通常的任务

在这个例子中,Textbox1中有一个class的代码,其代码如下

class TestClass
 public shared sub Hello(byval name as string)
  System.Windows.Forms.MessageBox.Show(name)
 end sub
End Class

1、引用Microsoft.Vsa.dll,Microsoft.VisualBasic.vsa.dll
2、
imports Microsoft.Vsa
Imports Microsoft.VisualBasic.Vsa
3、在模块级定义IVsaEngine 变量
dim m_VsaEngine as IVsaEngine

4、创建Microsoft.VisualBasic.Vsa.VsaEngine的一个实例
m_VsaEngine=new Microsoft.VisualBasic.Vsa.VsaEngine()
5、 设置RootNameSpace和RootMoniker
m_VsaEngine.RootNameSpace="Test"
m_VsaEngine.RootMoniker="myapp://Project1"

6、设置Site属性(注:site必须在RootMoniker后设置)

m_VsaEngine.Site=new MyVsaSite

7、创建一个IVsaCodeItem实例
 Dim codeItem As VsaCodeItem
codeItem = m_VsaEngine.Items.CreateItem("test", Microsoft.Vsa.VsaItemType.Code, Microsoft.Vsa.VsaItemFlag.Class)
        codeItem.AppendSourceText(TextBox1.Text)

8、编译并运行
        If m_VsaEngine.Compile() Then
            m_VsaEnigne.Run()
        End If

9、调用是通过Reflection进行的,为了简化这个调用过程,我用vb.net模拟了vsa sdk中的Runtime类Invoke的过程
       

Dim args() As Object = New Object() {"jjx"}

        Invoke("TestClass.Hello", args)

Invoke 的vb.net实现
 

Public Overloads Function Invoke(ByVal methodName As String, ByVal arguments() As Object) As Object
        If methodName Is Nothing OrElse String.Compare(methodName, "") = 0 Then
            Throw New ArgumentNullException("methodName")

        End If
        If v Is Nothing Then

        End If
        If Not m_VsaEngine.IsRunning Then
            m_VsaEngine.Run()


        End If
        Dim chs2() As Char = New Char() {"."}
        If methodName.Split(chs2).Length < 2 Then
            Throw New Exception("")

        End If
        Dim i As Integer = methodName.LastIndexOf(".")
        Dim str1 As String = methodName.Substring(0, i)
        Dim str2 As String = methodName.Substring(i + 1)
        Dim str4 = String.Concat(ScriptEngine.RootNamespace, ".", str1)
        Dim methodInfo As MethodInfo = ScriptEngine.Assembly.GetType(str4, True, True).GetMethod(str2)
        If Not methodInfo Is Nothing Then
            Return methodInfo.Invoke(Nothing, arguments)

        End If

    End Function

 

编译错误
通过实现IVsaSite接口的OnCompilerError可以了解编译错误信息
  

  Public Function OnCompilerError(ByVal [error] As Microsoft.Vsa.IVsaError) As Boolean Implements Microsoft.Vsa.IVsaSite.OnCompilerError
        Debug.WriteLine([error].Description)


    End Function

引致:http://www.soho-works.net/blog/post/464.html