随笔 - 89, 评论 - 163, 引用 - 33

导航

关于

标签

每月存档

最新留言

广告

在调试时怎样禁止JIT优化

 

[原文作者]:Jaredpar

[原文链接]:Disabling JIT optimizations while debugging

 

     如果你正在调试一个托管应用程序,却发现不能查看任何局部变量或者函数参数的值,这是因为

     托管代码在编译时已经被优化了。下面的内容将告诉你怎样解决这个问题。我会教大家一种非常简单的小技巧来利用.ini文件禁止代码优化。它不需要你重新编译你的应用程序并且只要几秒钟就能实现。

     创建一个.ini文件并添加如下内容:

     [.NET Framework Debugging Control]

     GenerateTrackingInfo=1

     AllowOptimize=0

     这个小技巧真的能帮助你节省调试的时间。虽然已经有其他人把它写进博客里,但是在过去几周我总是需要去搜索它,于是我就干脆也把它写进自己博客了以防以后需要。

posted on 2009-01-23 13:59:45 by vbcti  评论(0) 阅读(3403)

正确操作windows窗体的Timer事件

[原文作者]Jared Parsons                                       
 
     Windows窗体的时间(Timer)类允许用户在一个时间段内执行特定的操作。时间对象会在设定的时间内开始一个Tick事件,用户可以容易的响应这个事件。如果软件开发者想在在一个指定的时间段内检查一个特定的条件(比如2秒钟,我会在这篇文章中用两秒作为范例),这时这个事件就会非常有用。
 
     偶尔用户会惊奇的发现Tick事件会比期望当中的更快地被触发。比较在两个调用期间等待两秒钟而言,取而代之的是Tick事件几乎是在一个被调用的过程完成后就被立即被触发了。
 
     这里所发生的是这个事件在事件循环机制作用下所产生的状态变化。时间事件的间隔期是由现实世界的时间来计算的。所以直白的讲,每隔两秒钟windows将认为时间间隔结束,然后发送一个新的Tick事件消息。下一时间段的windows窗体事件就不会再执行代码,一个tick事件会被触发【1】。
 
     现在我们可以想象一下我们已经有如下的代码。
 
     Private Sub OnTimerTick () Handles m_timer.Tick
         RunSomeOperation ()
     End Sub
 
     考虑一下如果 RunSomeOperation 用时超过2秒钟将发生什么。Tick事件会在RunSomeOperation过程当中被实时的触发,另外一个Tick事件会等候处理。一旦我们离开OnTimerTick过程,我们会回到Windows窗体代码,这些代码会巡视到Tick事件并且促使触发它,让我们重新回到OnTimerTick过程。
 
     这是与大多数人的期望矛盾的。大多数人会期望Tick事件应该在窗体代码完成后的两秒被触发。
 
     要想解决这个矛盾,开发者可以在处理一个timer事件的时候停止时间计数器的计数。然后再退出事件处理程序后从新激活计数器。这会使windows从激活计数器时才开始计算时间间隔。这样做的结果是使得timer事件在代码停止执行后的两秒钟才被触发。请参考以下代码:
 
    Private Sub OnTimerTick () Handles m_timer.Tick
      M_timer.stop ()
      Try
             RunSomeOperation ()
       Finally
             M_timer.Start ()
       End Try
    End Sub
 
 
 
      【1】这不是100%正确。不过这确实是无论什么时候应用程序开始又一次的循环事件时的情况。循环事件(更加确切的说是当循环事件发生或没有发生的时候)也与我们的这篇讨论相关联。

posted on 2008-11-07 14:35:41 by VBCTI  评论(0) 阅读(3100)

VB XML 手册6:在VB中写XSLT转换

 
      大多数XSLT程序员对于下面这段复制一个XML文件的XSLT转换都非常熟悉。
<?xmlversion="1.0"encoding="utf-8"?>
<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:outputmethod="xml"indent="yes"/>
 
    <xsl:templatematch="@* | node()">
        <xsl:copy>
            <xsl:apply-templatesselect="@* | node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
        这种XSLT身份转换的应用十分普遍,因为它可以让你复制整个XML文档,并且会“访问”到每一个XML节点和属性。如果你添加一个模板,那么它就会对那些存在匹配的节点或属性进行转换,而那些不存在匹配的节点和属性只会被简单的拷贝。
        我们也可以用Visual Basic 中的XML Literals(包括LINQXMLXML的轴属性)来实现XSLT的转换,VB代码可以通过基于以下伪码的XML文档以递归的方式“访问”到每个节点或元素:
Starting with the root element, perform the following whenever you encounter a node
If the node is an element
If the element has attributes, transform or copy each attribute
If the element has child nodes, transform or copy each node
If the node is text, transform or copy the text
If the node is CData, transform or copy the CData
If the node is a comment, transform or copy the comment
If the node is a processing instruction, transform or copy the processing instruction
 
        对于手册中的这一方法,我们将创建一个抽象(MustInherit)基类来执行上面XML文档中的这段递归调用的伪代码。然后再创建一个继承于这个基类的子类来执行具体的转换。首先,我们将创建那个抽象基类和一个作为“起始点”的Transform函数,它以要被转换的XML文档(XDocument)作为输入,然后将转换后的文档返回。
 
Public MustInherit Class VBXmlTransform
 
 Public Overridable Function Transform(ByVal xmlDoc As XDocument) As XDocument
    Return <?xml version="1.0" encoding="utf-8"?>
           <%= ProcessElement(xmlDoc.Root) %>
 End Function
 
End Class
 
        接着,我们来添加那段要调用到每个XML节点(XNode)的逻辑代码,它包含了elements, text, CData等等。在代码中我们需要判断XML节点的类型从而调用相应的函数来进行转换或者对节点类型进行拷贝,并且返回结果,这个结果可能是一个拷贝而来的节点,也可能是一个经过转换的节点。这个方法即ProcessNode,下面是它的代码:
 
 Public Overridable Function ProcessNode(ByVal xmlNode As XNode) As XNode
' This method ignores DTD (XDocumentType) content.
 
    Dim nodeType = xmlNode.GetType()
 
    ' Because XCData inherits from XText, check for the XCData type before checking
' for XText.
 
    If nodeType Is GetType(XCData) Then Return ProcessCData(xmlNode)
    If nodeType Is GetType(XText) Then Return ProcessText(xmlNode)
    If nodeType Is GetType(XElement) Then Return ProcessElement(xmlNode)
    If nodeType Is GetType(XComment) Then Return ProcessComment(xmlNode)
    If nodeType Is GetType(XProcessingInstruction) Then Return _
      ProcessProcessingInstruction(xmlNode)
 
    Return xmlNode
 End Function
 
        接下来,我们添加一个强类型函数来处理每种节点类型以及属性。由于处理element的函数和其他的不一样,所以我们将稍后给出。处理其他的节点类型和属性的函数相当简单,因为基类的行为就只是拷贝文档,即每一个函数仅仅将其输入值返回。所以我们创建这段代码的目的也就是为了提供一个强类型函数,可以让我们在继承于它的子类的具体方法中来进行覆盖。下面是那些强类型函数(除ProcessElement函数):
 
     Public Overridable Function ProcessAttribute(ByVal xmlAttribute As XAttribute) As XAttribute
        Return xmlAttribute
     End Function
 
     Public Overridable Function ProcessCData(ByVal xmlCData As XCData) As XCData
        Return xmlCData
     End Function
 
     Public Overridable Function ProcessText(ByVal xmlText As XText) As XText
        Return xmlText
     End Function
 
     Protected Overridable Function ProcessComment(ByVal xmlComment As XComment) As XComment
        Return xmlComment
     End Function
 
     Public Overridable Function ProcessProcessingInstruction( _
       ByVal pi As XProcessingInstruction) As XProcessingInstruction
 
        Return pi
      End Function
 
 
        现在让我们来看看那个ProcessElement函数,处理element的方法之所以独特是因为它不仅有属性还有child节点,这些属性和child节点都需要被转换或者拷贝,所以我们必须为每个属性提供ProcessAttribute函数,并且为每个child节点提供ProcessNode函数。我们将把这些代码放入一个名为CopyElement的方法中,这样ProcessElement函数看起来就和其他的强类型函数一样,但是它将返回一个对CopyElement函数的调用,而不仅仅返回其输入值。CopyElement函数使用了XML Literals,嵌入式表达以及LINQXML来实现对XML element的拷贝,代码如下:
 
     Public Overridable Function ProcessElement(ByVal xmlElement As XElement) As XElement
         Return CopyElement(xmlElement)
     End Function
 
     Public Overridable Function CopyElement(ByVal xmlElement As XElement) As XElement
         Return <<%= xmlElement.Name %>
             <%= From attribute In xmlElement.Attributes() _
                 Select ProcessAttribute(attribute) %>>
             <%= From node In xmlElement.Nodes() _
                 Select ProcessNode(node) %>
           </>
     End Function
 
        上面就是我们所说的抽象类了,现在我们可以利用它来进行一些简单或复杂的身份转换了。让我们来看个例子吧:
     创建一个转换
 
        我们的例子将使用和手册1中相同的XML文件,它混合了来自几个不同命名空间的内容,从而提供了一个非常好的例子。这些示例文件中的内容在
< AdditionalContactInfo > element中可以找到: http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo schema。在contact info文件中有address信息,它包含了三种不同的元素:homePostalAddress physicalDeliveryOfficeName registeredAddressaddressType类型含有一个必需的元素PostalCode,下面我们可以创建一个简单的类来对<PostalCode>进行转换并将它重命名为<ZipCode>
 
        首先,我们需要导入那些源文档中不同的schemas,这些源文档中特定的schemas,对于抽象的VBXmlTransform类而言并不需要,但对我们继承而来的子类却是必需的。
 
    Imports <xmlns="http://SampleSchema/AWContacts">
    Imports <xmlns:aci="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo">
    Imports <xmlns:act="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
    Imports <xmlns:crm="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactRecord">
 
 
         接下来,我们创建一个继承于VBXmlTransform的类,这个子类叫做AWTransform,在这个子类中,我们覆盖了基类并且添加了新的代码,从而可以执行我们想要的任何转换。这样,我们就必须覆盖掉基类的ProcessElement方法,因为我们需要寻找所有名为PostalCode的元素,如果找到了就进行转换,如果没有找到,才会用基类的ProcessElement方法来处理。
 
   Class AWTransform
    Inherits VBXmlTransform
 
' Rename <act:PostalCode> to <ZipCode>.
' Create an XName object to use for comparisons. This will perform better than comparing
    ' xmlElement.Name.LocalName to a string.
 
    Private postalCodeXName As XName = _
      XName.Get("PostalCode", _
                "http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes")
 
    Public Overrides Function ProcessElement(ByVal xmlElement As XElement) As XElement
        Select Case xmlElement.Name
            Case postalCodeXName
                Return TransformPostalCode(xmlElement)
            Case Else
                Return MyBase.ProcessElement(xmlElement)
        End Select
 
        Return Nothing
    End Function
 
    Public Function TransformPostalCode(ByVal postalCodeElement As XElement) As XElement
        Return <ZipCode><%= postalCodeElement.Value %></ZipCode>
    End Function
  End Class
 
     转换文档
 
        为了实现转换文档,我们需要新建一个子类的实例AWTransform,然后将那个XML源文档传给Transform方法,代码如下:
 
        Dim xmlPath = My.Application.Info.DirectoryPath & "\..\..\AWContacts.xml"
        Dim savePath = My.Application.Info.DirectoryPath & "\..\..\TransformSave.xml"
 
        Dim xmlDoc = XDocument.Load(xmlPath)
 
        Dim transform As New AWTransform()
 
        Dim transformedDoc = transform.Transform(xmlDoc)
        transformedDoc.Save(savePath)
     其他示例
 
        让我们来看看一些其他可以添加到AWTransform类的例子。
        以下这段代码实现了我们怎样去转换一个现有属性的内容如果transform找到名为date的属性就将date值转换为一般的日期和时间格式。
 
    Private dateXName As XName = XName.Get("date")
 
    Public Overrides Function ProcessAttribute(ByVal xmlAttribute As XAttribute) As XAttribute
        If xmlAttribute.Name.Equals(dateXName) Then Return TransformDateAttribute(xmlAttribute)
 
        Return MyBase.ProcessAttribute(xmlAttribute)
    End Function
 
    Public Function TransformDateAttribute(ByVal dateAttribute As XAttribute) As XAttribute
        Dim dateValue As New DateTime()
        If DateTime.TryParse(dateAttribute.Value, dateValue) Then _
            dateAttribute.Value = dateValue.ToString("G")
 
        Return dateAttribute
    End Function 
 
        接下来的这段代码实现了我们怎样从转换后的文档中去掉data:如果transform找到
CData section就返回Nothing,这样CData section就不会存在于结果文档中。
 
    Public Overrides Function ProcessCData(ByVal xmlCData As XCData) As XCData
        Return Nothing
    End Function

posted on 2008-11-07 14:27:45 by VBCTI  评论(0) 阅读(2626)

VB XML手册4: 从Node属性获得内部XML内容

[原文链接]:VB XML Cookbook, Recipe 4: Get Inner XML from the Nodes Property (Doug Rothaus)

[原文作者]:Doug Rothaus

 

     手册3告诉我们一种使用XML Descendant axis property和使用 ReplaceWith来操作混合XML的方法。这是ID转换的一种方式,我们将在下一篇文章中提到另外一种方法。这里有一个 第三章没有提到的主特性,这个主功能需要你进行完全化地功能性特性转变。那就是从一个元素中复制内部XML的概念。你可以从Node属性中获得元素的内部XML.
第三章将电子邮件对象通过特性转换将AdventureWorks示例文档转换成以原版格式保存的HTML 文档并提供它的超链接。然而,为了让第三章所作的事情简单化,我忽略了这样一件事情,那就是<eMailAddress> 元素的schema(可以在ContactTypes.xsd schema 文件中找到)既允许<eMail> 元素包括邮件地址,也允许<SpecialInstructions> 元素作为一个辅助信息比如用电话号码将电子邮件地址替换掉,还有合适打电话等等。<SpecialInstructions> 元素可以包含任何ContactTypes.xsd 中其他元素的ID. 为了让<eMailAddress> 元素包含所有信息,我们必须还要包含一些特别的指导。(:你可以从 手册3 的文章中下载XML文档以及相关的schemas 文件)
 
     从电子邮件地址转换成<eMail> 元素非常简单,因为<eMail> 元素只包含电子邮件地址的值。然而要转换<SpecialInstructions> 元素却并非那么简单因为元素本身既包含子元素也包含值。如果你想得到<SpecialInstructions> 元素的内嵌值, 你就会得到元素里面的文本内容, 任何XML内容都不会被查找到.这也就是被称作是元素的内部内容。
     如果你熟悉System.XML这个命名空间下的类的话,你将会立即想到这个方法。这个解决方案是针对元素中嵌入的XML内容而不是针对文本内容(值属性)。然而System.XML类既公开InnerText属性也公开InnerXml属性,但是却不支持LINQXML.嵌入的文本内容将由Value 这个属性来返回,嵌入的XML内容却由Node 这个属性。它们有何不同?InnerXml 将返回一个XML格式的字符串,它必须被重新转换成XML对象。Node 属性返回的是一个XML对象的LINQ集合,对于它你可以熟练操作或者逐个字符地整个地嵌入到XML中,这样就让Node 属性成为XML转换的有效工具。
     所以,结合我们已经知道的,让我们看一看一个例子中的Value属性(嵌入文本)Node(嵌入XML)属性。我们这里有一个Function(模板)TransformEmail, 它将把XML数据源转换为HTML.在这里我们用Value 属性得到了电子邮件地址,并且我们调用了GetSpecialInstructions 方法将需要包含的特有信息也嵌入到了HTML之中。GetSpecialInstructions 方法返回HTML 标记和<SpecialInstructions> 元素的内部XML,因为这些内部XML还包含其它混合标记,包括文本以及其他XML内容。
 Private Sub TransformEmail(ByVal email As XElement)
    Dim emailHtml = <div class="Email">
                      <a href=<%= "mailto:" & email.<act:eMailAddress>.Value %>>
                        <%= email.<act:eMailAddress>.Value %>
                      </a>&#32;
                      <%= GetSpecialInstructions(email.<act:SpecialInstructions>) %>
                    </div>
 
    email.ReplaceWith(emailHtml)
 End Sub
 
 Private Function GetSpecialInstructions( _
    ByVal instructions As IEnumerable(Of XElement)) As IEnumerable(Of XElement)
 
    If instructions IsNot Nothing Then _
      Return From instruction In instructions _
             Select <span class="SpecialInstructions">
                      <%= instruction.Nodes %>
                    </span>
 
    Return Nothing
 End Function

posted on 2008-11-03 17:27:37 by VBCTI  评论(0) 阅读(2369)

VB XML手册5:"Halloween"问题

[原文作者]:Doug Rothaus

[原文链接]:VB XML Cookbook, Recipe 5: The “Halloween” Problem (Doug Rothaus)

    在前两次的手册中,我们讲了关于用ReplaceWith这个方法来进行身份转换.如果这个方法满足了你的需要,它会在你的代码中引发另外一个问题--"Halloween".让我们看看这个问题到底是怎样的,怎么样去解决.(详细的"Halloween"问题和解决方案可以参考这个文档).

    "Halloween"描述的场景是,你有一个以某种方式更新的数据集同时这个数据集又在被遍历的话,你会得到一个空引用的异常,更坏的是,你的代码可能会因为修改错误的数据而崩溃.例如前面两个手册用到的代码段:

Private Sub Recipe5(ByVal xmlPath As String)

    Dim xmlDoc = XDocument.Load(xmlPath)

 

    Dim info = xmlDoc.<Contacts>.<Contact>.<aci:AdditionalContactInfo>

 

    ' Replace e-mail address tags with mailto links.

    For Each email In info...<act:eMail>

      TransformEmail(email)

    Next

  End Sub

 

  Private Sub TransformEmail(ByVal email As XElement)

    Dim emailHtml = <div class="Email">

                      <a href=<%= "mailto:" & email.<act:eMailAddress>.Value %>>

                        <%= email.<act:eMailAddress>.Value %>

                      </a>&#32;

                    </div>

 

     email.ReplaceWith(emailHtml)

  End Sub

 

    如果你运行这段代码,就会得到下面的异常:

 

      这个异常的出现是因为For... Each循环正在循环用<eMail>元素查询出来的结果。在第一次调用TransformEmail个方法的时候,<eMail>这个元素已经被HTML替换掉了,结果,这个查询引用的就是已经不存在的XML元素了。

    要怎么解决这个问题呢?有几个解决方案,第一,你可能你已经注意到了在前面的手册中,把这个查询的结果用ToList方法返回一个List。像下面的代码

    For Each email In info...<act:eMail>

    改为:

    For Each email In info...<act:eMail>.ToList()

    返回一个List,表明要处理的就不再是一个查询结果,而更新就会作用到查询上面,例如用HTML替换XML,这样就不会影响到List。

    其他比较普遍的解决方案就是你的代码不要修改原本的文件,把结果放到新的XML文件中。下一个手册我会讲怎么做。


posted on 2008-11-01 08:51:45 by VBCTI  评论(1) 阅读(3196)

LINQ手册8:使用LINQ查询XML(Doug Rothaus)

配料:
·         Visual Studio 2008 (Beta2或更高版本)
类别:LINQ-ToXML
 
步骤:
·         使用VB 创建一个新的Console Application
·         创建RSS文档。添加以下代码到Sub Main中。
    Dim rss = <?xml version="1.0"?>
              <rss version="2.0">
                <channel>
                  <title>LINQ to XML in Visual Basic</title>
                  <description>Sample RSS Feed</description>
                  <language>en-us</language>
                  <pubDate>Tue, 18 Sep 2007 00:56:12 GMT</pubDate>
                  <item>
                    <title>Basic Instincts: Lambda Expressions</title>
                    <description>A new feature added to Visual Basic 9 to
                                 support Language Integrated Queries (LINQ),
                                 which adds data programmability to
                                 Visual Basic.</description>
                    <pubDate>Thu, 27 Sep 2007 23:54:55 GMT</pubDate>
                  </item>
                  <item>
                    <title>Visual Basic Pack for Visual Studio 2005 SDK</title>
                    <description>The Visual Basic Pack for the Visual Studio
                                 2005 SDK includes SDK samples converted into
                                 the Visual Basic language and a new wizard for
                                 generating Visual Basic-based integration
                                 packages for Visual Studio.</description>
                    <pubDate>Mon, 17 Sep 2007 23:58:49 GMT</pubDate>
                  </item>
                  <item>
                    <title>XML to Schema Tool</title>
                    <description>The XML to Schema tool is a free project item
                                 template to automate creation of XML schema
                                 sets from any number of XML documents. If you
                                 are working with Language Integrated Queries
                                 (LINQ) to XML in Visual Basic 9, this utility
                                 can significantly improve your editing
                                 experience by adding XML schemas (.xsd files)
                                 to your project that add IntelliSense for XML
                                 properties.</description>
                    <pubDate>Mon, 17 Sep 2007 23:59:43 GMT</pubDate>
                  </item>
                  <item>
                    <title>Line and Shape Controls in the Power Packs</title>
                    <description>Download the latest version of the Visual
                                 Basic 2005 Power Packs which now includes Line
                                 and Shape controls that enable you to draw
                                 lines, ovals, and rectangles on forms and
                                 containers at design time making it much easier
                                 to enhance the look of your user
                                 interface.</description>
                    <pubDate>Mon, 20 Aug 2007 20:24:25 GMT</pubDate>
                  </item>
                </channel>
              </rss>
 
   VB中你可以使用LINQ语法查询XML就像你在SQL Server或者其它数据库上查询数据和数据集合一样。不同之处在于你如何去查找XML 元素和属性。在VB中有些XML 的特性允许你使用类数据对象那样查找XML 的元素和属性。
   举例来说,要查找之前创建的XDocument对象中的<channel>元素,你只要编写一行简单的代码:rss.<rss>.<channel>.尽管这看起来只是查找出一个<channel>元素,但事实上代码返回的是<rss>对象中所有<channel>子元素的集合。这样你就能通过Index来查找特定的<channedl>元素,或者就像我们在标题中看的那样通过执行LINQ查询所有的元素集合。为了能查找XML元素的任意子元素,可以使用descendant语法"...",示例rss.<rss>...<title>.为了查找属性,可以使用attribute语法"@,示例rss.<rss>.@version。这些为了在XDocumentXElement中查找元素和属性的语法被称之为XML Axis属性。
注意:在VBXML特性包含了XML智能感知,它可以在我们编码过程中使用XDocumentXElement这些LINQ to XML对象时提供它们的XML属性以及子元素列表。要启用XML智能感知只需将XML结构定义(XSD)文件添加到你的项目中。VB中的XML工具会在你没有XSD文件的前提下,通过XML文件的内容创建一个XSD文件。更多信息,请看XML IntelliSense in Visual Basic
   通过在VB中使用XML Axis属性,我们可以使用LINQ来查询XML内容。举例来说,以下的查询在RSS feed中执行了一次搜索,搜索的内容是<item><title><description>元素。添加代码到Sub Main中,并将其置于XDocument对象之后。
    Dim itemList1 = From item In rss.<rss>.<channel>.<item> _
                    Where item.<description>.Value.Contains("LINQ") Or _
                          item.<title>.Value.Contains("LINQ")
 
    Console.WriteLine("Items containing 'LINQ'" & vbCrLf)
    For Each item In itemList1
      Console.WriteLine(vbTab & "Title: " & item.<title>.Value)
      Console.WriteLine(vbTab & "Description: " & item.<description>.Value)
      Console.WriteLine()
    Next
 
   注意示例代码的搜索是从XML元素的Value属性寻找匹配值。Value属性将从XML元素中返回的内容做为字符串。如果不这样处理的话,XML Axis属性将会对应元素名称的元素集合。但是当搜索XML属性时,你并不需要指定Value属性。这种情况下,XML Axis属性默认返回第一个匹配属性的Value.
   由于Value属性总是返回字符串,你或许需要将其转化成其它指定的类型来执行你的查询。举例来说,以       下代码示例搜索的是过去20天发布的RSS。添加代码到Sub Main末尾。
    Dim itemList2 = From item In rss.<rss>.<channel>.<item> _
                    Let pubDate = DateTime.Parse(item.<pubDate>.Value) _
                    Where pubDate >= _
                          DateTime.Now.Subtract(New TimeSpan(20, 0, 0, 0)) _
                    Select item
 
    Console.WriteLine("Items published in the last 20 days" & vbCrLf)
    For Each item In itemList2
      Console.WriteLine(vbTab & "Title: " & item.<title>.Value)
      Console.WriteLine(vbTab & "Publish Date: " & item.<pubDate>.Value)
      Console.WriteLine()
    Next
 
    按下F5查看代码运行情况。
 

posted on 2008-10-29 11:25:07 by VBCTI  评论(2) 阅读(3225)

让PInvoke简单

[原文作者]Jared Parsons
[原文链接]Making PInvoke Easy
 
     我非常兴奋的宣布我们最近发布了一个工具,这个工具对我们在托管代码中使用PInvoke非常有用。这个工具的名 字是PInvoke Interop Assistant”,“PInvoke Interop Assistant”作为PInvokeReverse PInvoke场景的一部分已经被包含在MSDN文章中。
 
    下面的链接是文章和工具
·         ToolCLRInsideOut2008_01.exe
 
 
   开发这个工具背后的动力是写PInvoke是一个艰难并且乏味的任务。有很多规则必须遵守,很多异常必须要考虑到。所有在简单的数据结构之外的东西必须专心的做,C当中微妙的语义会很大程度上改变所需的签名。不正确的翻译经常会导致不明确的异常或者崩溃。
 
   简而言之,这个差事没有什么乐趣。
 
   这个工具可以用很多方式让PInvoke产生更简单的进程。目标是为structunionsenumsconstantsfunctionstypedefs等等产生尽可能简单的托管代码。这些代码可以在VBC# 中生成。
 
   工具中三个选项卡的GUI版本:
1. Siglmp Search: 搜索常用的方法,然后翻译成托管代码。
2. Siglmp Translate Snippet:直接翻译C代码到托管的PInvoke签名中去。
3. SigExp:转换托管的二进制代码到C++ Reverse PInvoke 场景中。
 
   前面两个是我的工作部分,也是代表PInvoke的场景。第三个是Ladi Prosek写的,这部分另外一篇文章会讲到。我们选择SiglmpSigExp这两个名字来反映工具tblimp/tlbexp,因为他们有差不多的方法。
 
    直接翻译C代码到PInvoke签名中
 
    在PInvoke中大部分的冒险是,开发者想用托管代码中的一小部分C代码。典型的是一两个有C结构体的方法。以前,所有这样的情况需要从一开始就翻译进托管代码中。用这个工具,你只需要把代码粘贴到这个工具里面,然后它就会生成相应的签名。
 
    例如假设你想翻译下面的C代码到VB
 
struct S1
{
 int a;
 char[10] b;
};
 
float CalculateData(S1* p);
 
    把工具打开,转换到“Siglmp Translate Snippet”选项。粘贴这些代码,然后按Generate按钮。
    你也可以按“Auto Generate“,然后看着你键入的代码更新。
 
    这种翻译不限制于内置的 C类型。它还可以解决大多数通用的windows类型,例如HANDLEDWORD所有的这些到复杂的结构体例如WIN32_FIND_DATA
 
    搜索常用的方法
 
    通常开发者想在托管代码中用他们熟悉的C函数。这也是一个乏味的任务,因为如果这个签名现在还不是可以得到的,那么你就要从头编码。如果你不知道到哪个头文件里面去查的话,加一个常量是不易处理的。
    这个工具提供了一个有常用的方法,结构体,常量等的数据库。基本上windows.h包含了所有的东西。转换到Siglmp的搜索键,键入你想搜索的名字,然后敲generate。例如你想看WM_PAINT的值。   
     另外,工具的这部分还会做附属的分析。例如,选择一个有C结构的方法,它会自动生成方法的结构。例如,你选FindFirstFile,它会知道这个方法依赖于WIN32_FIND_DATA这个结构。另外,它还会注意到WIN32_FIND_DATA依赖于FILETIME然后会生成这两个到方法里面去。
 
<System.Runtime.InteropServices.StructLayoutAttribute( _
    System.Runtime.InteropServices.LayoutKind.Sequential, _
    CharSet:=System.Runtime.InteropServices.CharSet.[Unicode])> _
Public Structure WIN32_FIND_DATAW
    '''DWORD->unsigned int
    Public dwFileAttributes As UInteger
    '''FILETIME->_FILETIME
    Public ftCreationTime As FILETIME
    '''FILETIME->_FILETIME
    Public ftLastAccessTime As FILETIME
    '''FILETIME->_FILETIME
    Public ftLastWriteTime As FILETIME
    '''DWORD->unsigned int
    Public nFileSizeHigh As UInteger
    '''DWORD->unsigned int
    Public nFileSizeLow As UInteger
    '''DWORD->unsigned int
    Public dwReserved0 As UInteger
    '''DWORD->unsigned int
    Public dwReserved1 As UInteger
    '''WCHAR[260]
    <System.Runtime.InteropServices.MarshalAsAttribute( _
        System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=260)> _
    Public cFileName As String
    '''WCHAR[14]
    <System.Runtime.InteropServices.MarshalAsAttribute( _
        System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=14)> _
    Public cAlternateFileName As String
End Structure
 
<System.Runtime.InteropServices.StructLayoutAttribute( _
    System.Runtime.InteropServices.LayoutKind.Sequential)> _
Public Structure FILETIME
    '''DWORD->unsigned int
    Public dwLowDateTime As UInteger
    '''DWORD->unsigned int
    Public dwHighDateTime As UInteger
End Structure
 
Partial Public Class NativeMethods
    '''Return Type: HANDLE->void*
    '''lpFileName: LPCWSTR->WCHAR*
    '''lpFindFileData: LPWIN32_FIND_DATAW->_WIN32_FIND_DATAW*
    <System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint:="FindFirstFileW")> _
    Public Shared Function FindFirstFileW( _
        <System.Runtime.InteropServices.InAttribute(), _
            System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> _
            ByVal lpFileName As String, _
        <System.Runtime.InteropServices.OutAttribute()> _
        ByRef lpFindFileData As WIN32_FIND_DATAW) As System.IntPtr
    End Function
End Class
 
    翻译大量的代码
 
   小的翻译器适合翻译小的代码段。如果你想要翻译大量的代码,像彼此依赖的头文件的话,小的翻译器就不会工作得很好了。你应该用这个工具的命令行的版本来翻译大量的代码。sigimp.exe。它是被设计用来进行很多头文件的翻译工作,然后产生大量的输出。
    结语
   以前这个工具就像是我项目的宠物。我十分的兴奋,现在客户可以利用它的优点,我也期待你们给我回馈。稍后,我会帖更多关于这个工具是怎么工作的文章。

posted on 2008-10-28 14:23:20 by VBCTI  评论(3) 阅读(2929)

#6 知道么,你现在可以编辑自动完成代码段了

[原文作者]:Lisa Feigenbaum
 
 
  你用过自动完成代码段么(参看VB2005中的介绍)?如果用过的话,你可能会注意到编辑文件时出现的绿色高亮提示,它们伴随着编辑文件的始终。我们已经收到很多关于编辑自动完成代码段时,高亮提示显示很散乱的抱怨,所以,在VB2008中我们改进了使用自动完成代码段时的用户体验。同时也增加了许多新的命令来控制高亮提示是否隐藏。接下来让我们来看一下在VB2008中有哪些改进
    自动完成代码段可以手动(右键点击->插入自动完成代码段)或自动插入。在VB2008中,所有根据关键字自动插入的自动完成代码段都是显示在自动完成提示框中的,例如下图:
  
 当我输入‘pro’时,VB2008会自动过滤出符合条件的输入,因为属性自动完成代码段的快捷插入是根据关键字(‘property’)来判断的,所以会显示在自动完成提示框内,在这段提示中,解释了如何从自动完成提示框插入自动完成代码段,当点两下‘tab’键,属性自动完成代码段就会自动插入。
   高亮显示的部分就是传说中的自动完成代码段的可替换处’, 它们的用意在于显示出可能需要在我自己程序中改动的部分(例如变量名称、变量类型等等)。
   还有一些功能可能看上去比较有用,你可以选择一个自动完成代码段的可替换处,把鼠标指针悬停在它上面,然后那里会显示一条提示,来告诉你如何替换这个地方。
  
  在用类似的语言写代码遇到像上面那个属性的例子时,自动完成代码段是很有用的,而且当你需要做其他一些特定工作,自动完成代码段同样非常好用。自动完成代码段同样提供了一个好处,你写的自动完成代码段可以被分享给一个组,因为它本身能告诉别人如何使用自己。
   另一个自动完成代码段的有趣功能就是链接可替换处。当自动完成代码段中有些特定的部分需要保持一致的时候,VB会把那些部分链接到一起,这样如果你想改动它们,你只需改动一处就可以了。在下面的例子里,我将把属性自动完成代码段中的第一个高亮显示的部分替换掉:
  
 现在如果我把光标从这个部分切换走,其它两处链接可替换处就会被替换掉:
   
  那么,我就修改了我的自动完成代码段:
  当我完成修改的时候,高亮显示又会散落开来,让我们看到这么多烦人的绿色,在VB2008里面,一旦我在离开自动完成代码段范围之后打字,高亮显示就消失了。
 
   注意:在C#里面,关闭高亮显示是由点击回车键触发的,在VB中,任何在自动完成代码段范围外的编辑都会触发将高亮显示关闭,因为编译器认为这时自动完成代码段编辑工作已经结束了。
因此当你完成自动完成代码段编辑后会觉得很舒服,因为烦人的绿色色块没有了,可是,有时候你会希望回头来编辑自动完成代码段,并继续使用那些方便的功能。这时,你可以使用一个新的编辑器命令,光标移到你想编辑的自动完成代码段上,点右键。
 
  
 选择'显示自动完成代码段高亮提示,然后高亮的绿色又会出现,同时前面提到的那些功能也会启用:链接可替换处,替换处提示等等。
 
  
 当你完成了自动完成代码段编辑之后,你可以像前面提到的在自动完成代码段范围外作编辑动作来使提示消失,你也可以使用右键菜单中的隐藏高亮显示命令。
  
 如你所见,绿色又消失拉!
 
 
 

posted on 2008-10-20 10:58:28 by VBCTI  评论(0) 阅读(3035)

你知道吗?智能感知(IntelliSense)无处不在

[原文作者]: Lisa Feigenbaum

[原文链接]: 1 Did you know? IntelliSense Everywhere (Lisa Feigenbaum)

 

你知道VB2008里面所有智能感知的所在么?如果你跟我一样,那么一旦尝试使用了2008智能感知之后你将再也不想使用2005了。

VB的主要使命就是成为编.net相关应用程序最有效的工具。VBIDE 工具当然服务于这一使命,智能感知尤其显著。如下是如何利用智能感知使你更高效的方法:

1. 更快地键入:智能感知识别子补齐能节省你的按键次数;

2. 更少的错误:智能感知根据当前上下文提供有效的选项以防止编程错误;

3. 更短的搜索时间:智能感知通过显示有效列表中的成员名以节省你的时间;

4. 启发性:智能感知通过显示所有的可能用到的代码来帮助你决定以下的编程

当然,除了听我一直在这说为什么它是如此如此的好之外,为什么不自己尝试一下呢?看看下面的这几种你能在VS2008中找到VB智能感知的地方的图片。

关键词

文件级

看看那些IDE中的VB语言帮助提示,谁还会需要按F1呢!

声明级

节省打这些这么长的关键字的时间!

使用智能感知能避免错误声明。比如,Property不能在文档层声明。(如果你试图在那里声明一个,会显示编译错误) 这样,你在文件层调用智能感知的话, Property”就不会在提示列表中出现。

但是属性是能够在类层里面声明定义的,这样你如果试图在一个类里面声明一个属性的话,那个关键字就会在提示列表中出现。

 

行中间的验证也是类似的。 比如,属性不能被多继承,这样如果我打了MustlInherit然后调用提示下拉列表, Property”也不再出现了。

 

智能感知 是一个非常好的工具,它能帮助你纠正代码中的语法错误!它能将你从把这些规则记在脑子里的额外负担中解脱出来。

方法级

 如你所想,关键词智能感知在这里也同样适用。这里是几个实例:

 

 

标识符 (变量名, 方法名, 类型名等等)

在行的开头。。。

智能感知现在在一行的开头出现。 上面的例子显示了方法里面关键字的智能感知。其实标识符也会在那显示的,下面是几个例子:

你现在能用 智能感知来记住你的方法名:

 

给一个变量成员赋值也不是那么乏味的工作了,当你发现你不需要打全变量名字的时候!(如下)

 

在一个表达式里面。。。

VB里面有很多的表达式,现在你能体会对支持表达式智能感知的乐趣了。 下面是些相关实例:

等号之后

二元符之后

响应一个函数调用:

函数中return +Space 之后(不用在写函数返回值的时候再担心记不住你所有的局部变量名了,因为智能感知会帮你记住的。)

在语句中

等等等等。 VS2008里面还有很多智能感知出现的地方,不能一一列举了。我希望上面所列出来的这些成功传达给你了智能感知这个理念。

posted on 2008-02-19 10:48:00 by VBCTI  评论(12) 阅读(5601)

Powered by: Joycode.MVC引擎 0.5.2.0