Click to Rate and Give Feedback
Related Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
More ...
Articles by this Author
In this month’s installment of .NET Matters, columnist Stephen Toub answers reader questions concerning asynchronous I/O .

By Stephen Toub (July 2008)
This month Stephen Toub discusses asynchronous stream processing.

By Stephen Toub (March 2008)
This month Stephen Toub explains how to make the most of dual processors when running encryption and compression tasks.

By Stephen Toub (February 2008)
The author creates a managed wrapper to use the new IFileOperations interface in Windows Vista from managed code.

By Stephen Toub (December 2007)
Find out how to use finalizers as a way to warn developers who use your custom types when they are garbage collected without having been disposed of correctly.

By Stephen Toub (November 2007)
This month Stephen Toub discusses deadlocks that can occur when synchronizing threads.

By Stephen Toub (October 2007)
Stephen Toub and Shawn Farkas discuss creating an adapter that takes the functionality of RNGCryptoServiceProvider and adapts it to the interface of Random.

By Stephen Toub and Shawn Farkas (September 2007)
Stephen Toub gets nostalgic as he prepares to leave MSDN Magazine.

By Stephen Toub (August 2007)
More ...
Popular Articles
OBA solution patterns help architects and developers build Office Business Applications (OBAs). This article introduces the seven core OBA solution patterns and applies one to a real-world problem.

By Steve Fox (March 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
One-time passwords offer solutions to dictionary attacks, phishing, interception, and lots of other security breaches. Here's how it all works.

By Dan Griffin (May 2008)
Here we present a rundown of the various language paradigms of CLR-based languages via short language introductions and code samples.

By Joel Pobar (May 2008)
More ...
Read the Blog
Windows Presentation Foundation (WPF) offers excellent support for managing the display and editing of complex data. In the December 2007 edition of MSDN Magazine, John Papa did a great job of explaining essential WPF data binding concepts. ...
Read more!
The most fundamental form of Web testing is HTTP request/response testing. This involves programmatically sending an HTTP request to the Web application, fetching the HTTP response, and examining the response for an expected value. In the May 2008 issue of MSDN Magazine, Read more!
In the November issue of MSDN Magazine, Jeffrey Richter demonstrates some recent additions to the C# programming language that make working with the APM significantly easier. In the June ...
Read more!
The July 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Data Services: Develop ...
Read more!
The June 2008 issue features the first installment of a new MSDN Magazine column on software design fundamentals. We’ll discuss design patterns and principles in a manner that isn't bound to a specific tool or lifecycle methodology. In this issue, Jeremy Miller starts the Patterns in Practice column ...
Read more!
In the April 2008 issue of MSDN Magazine, Kenny Kerr introduced the Windows Imaging Component (WIC), showing you how you can use it to encode and decode different image ...
Read more!
More ...
New information has been added to this article since publication.
Refer to the Editor's Update below.

.NET Matters
XML Comments, Late-bound COM, and More
Stephen Toub

Code download available at: NETMatters0406.exe (174 KB)
Browse the Code Online

Q I'd like to use the XML documentation for a method from within that method. Is this possible? I'd like to be able to do the following:
/// <summary>Usage: myApp.exe file1.dat file2.dat ... fileN.dat</summary>
public static void Main(string [] args)
{
        if (args.Length == 0)
        {
            Console.WriteLine(XmlComments.Current.Summary.InnerText);
            return;
        }
        •••
}
Does any class like this exist in the Microsoft® .NET Framework?
Q I'd like to use the XML documentation for a method from within that method. Is this possible? I'd like to be able to do the following:
/// <summary>Usage: myApp.exe file1.dat file2.dat ... fileN.dat</summary>
public static void Main(string [] args)
{
        if (args.Length == 0)
        {
            Console.WriteLine(XmlComments.Current.Summary.InnerText);
            return;
        }
        •••
}
Does any class like this exist in the Microsoft® .NET Framework?

A The C# compiler is able to extract XML comments from C# source files. If at compile time, the /doc command-line option (or the equivalent option in the Visual Studio® .NET IDE) is used to specify a target documentation file, all of the comments are extracted from the source files and are written in an XML format to the target file. Visual Studio .NET can then use this file to display IntelliSense® when the XML file is in the same directory as the compiled assembly (the documentation file must also be named the same as the assembly, with a .xml extension). Both the Visual C++® and Visual Basic® compilers will support this feature in Visual Studio 2005.
A The C# compiler is able to extract XML comments from C# source files. If at compile time, the /doc command-line option (or the equivalent option in the Visual Studio® .NET IDE) is used to specify a target documentation file, all of the comments are extracted from the source files and are written in an XML format to the target file. Visual Studio .NET can then use this file to display IntelliSense® when the XML file is in the same directory as the compiled assembly (the documentation file must also be named the same as the assembly, with a .xml extension). Both the Visual C++® and Visual Basic® compilers will support this feature in Visual Studio 2005.
There are no classes in the .NET Framework written specifically for the purpose of mining and working with these XML comments, but functionality exposed from the System.Xml namespace can be used to make that task quite straightforward. In fact, in the code download for this column I've included a class that lets you use the syntax you've described.
In order to retrieve the XML documentation for a specific type or class member, you first need to find the XML file containing that documentation. To do that, you need to know in which assembly the type or class member is declared. Given the correct MemberInfo, you can use the MemberInfo.DeclaringType to get the Type that declares the member (in the case where you want the documentation for a Type, you don't need to obtain its DeclaringType as you already have a valid Type object). The assembly that declared this type can then be found using the Type's Assembly property, and the Assembly instance returned from that property exposes its file location on disk through the Location property. You can then substitute .xml for the extension of the assembly file and load the XML document from that location into an XmlDocument. Note that most of the assemblies in the .NET Framework are loaded from the Global Assembly Cache (GAC), but their XML documentation files are in the runtime directory. If the system fails to load the documentation from the assembly's folder, try the location returned by RuntimeEnvironment.GetRuntimeDirectory (see last month's column for more information).
Figure 1 Accessing XML Comments Programmatically 
Once you have the XmlDocument loaded with the assembly's XML comments, XPath expressions can be used to find the comments for the specified MemberInfo. This approach is diagrammed in Figure 1 and the code that retrieves the XmlNode is shown in Figure 2, creating an XPath expression based on the documentation at Processing the XML File.
I've created the XmlComments class so that the constructor takes the MemberInfo for which you want the comments. The constructor retrieves the XmlNode for the member's comments if one is available and uses XPath queries to parse the results looking for nodes and node lists that represent the summary, method parameters, exceptions that can be thrown, and so on. These nodes and node lists are then made available through public properties on XmlComments such as Summary and Exceptions. In order to support the syntax in your question, I've added a static Current property that uses the StackTrace class to retrieve the frame for the calling method and then uses the associated MethodInfo in order to construct an XmlComments instance:
public static XmlComments Current
{
        get { return new XmlComments(
                  new StackTrace().GetFrame(1).GetMethod()); }
}
There are a few corner cases I needed to be aware of when writing this, the most noticeable being accessor methods for properties and events. Accessors don't have their own XML comments, so given a MethodInfo for an accessor I need to be able to access the parent MemberInfo. One approach would be to use simple string manipulation to parse the name of the property or event from the accessor's name (for example, trimming off the "get_" or "set_" from the beginning of the name). I opted for a slightly more robust approach. For a given type, I store a Hashtable that maps accessor MethodInfo objects to their parent MemberInfo (which I create by looping over all properties and events in a Type, adding to the table all accessors found). When I need to check if a method is an accessor, I can query this table; if the MethodInfo exists as a key in the table, then not only is it an accessor but I also have immediate access to the MemberInfo for the parent which I can pass to the GetComments method shown in Figure 2 instead of the original MethodInfo for the accessor.
Of course, this whole solution only works if you build the XML comments for your application. And it's important to remember that the XML comments are not compiled into the assembly but rather into a separate .xml file, which means any solution that uses this technique should be tested with and without the .xml file present, in the correct location, and correctly named.

Q I'm trying to access a COM component at run time, but I don't have an interop assembly for it. Is it still possible for me to use it? I've considered dynamically generating an assembly when I need it, but that seems like overkill. The problem is that I'm writing a generic utility class in .NET and I won't know the ProgID of the COM component at compile time. It does implement IDispatch.
Q I'm trying to access a COM component at run time, but I don't have an interop assembly for it. Is it still possible for me to use it? I've considered dynamically generating an assembly when I need it, but that seems like overkill. The problem is that I'm writing a generic utility class in .NET and I won't know the ProgID of the COM component at compile time. It does implement IDispatch.

A The Type class exposes a method, GetTypeFromProgID, that you can use for this very scenario (you can use Type.GetTypeFromCLSID if you know the CLSID rather than the ProgID). You supply it with the ProgID of your component and it'll return to you a Type that describes it. You can then use the Activator class to create an instance of the component and various methods on Type, such as InvokeMember, SetProperty, and GetProperty, to access it.
A The Type class exposes a method, GetTypeFromProgID, that you can use for this very scenario (you can use Type.GetTypeFromCLSID if you know the CLSID rather than the ProgID). You supply it with the ProgID of your component and it'll return to you a Type that describes it. You can then use the Activator class to create an instance of the component and various methods on Type, such as InvokeMember, SetProperty, and GetProperty, to access it.
To make it easier to work with, I've created the helper class shown in Figure 3 that makes performing the most common operations easier. As an example, the following code creates an instance of the SharePoint.StssyncHandler COM component and queries its GetStssyncAppName method to determine which application on your machine handles the stssync protocol:
using(LateBoundComHelper lb = 
    new LateBoundComHelper("SharePoint.StssyncHandler"))
{
    string stsSyncHandler = (string)lb.Invoke("GetStssyncAppName");
}
With Microsoft Outlook® 2003 installed, stsSyncHandler will most likely be set to "Outlook".
As an aside, a similar helper class exists buried in the depths of System.Web. Using your favorite disassembler or decompiler, find the System.Web.Mail.SmtpMail class. SmtpMail declares a nested class named LateBoundAccessHelper that it uses to provide late-bound access to CDONT.NewMail on Windows NT® and also to CDO.Message on Windows® 2000 and higher.
If for some reason you still want to dynamically generate an assembly from a COM type library, you can use the ConvertTypeLibToAssembly method on the System.Runtime.InteropServices.TypeLibConverter class to generate the assembly for you. In fact, the tlbimp.exe and tlbexp.exe utilities included with the .NET Framework SDK are wrappers around this class (tlbimp.exe uses ConvertTypeLibToAssembly, while tlbexp.exe uses ConvertAssemblyToTypeLib). An example of its usage is available at TypeLibConverter.ConvertTypeLibToAssembly Method.

Q My team uses Debug.Assert throughout our Windows Forms app. When an assertion fails, an assertion dialog is displayed. I'd like to be able to control when this dialog is displayed based on certain environmental conditions, but I don't want to have to change every call to Assert to account for this. Is this possible?
Q My team uses Debug.Assert throughout our Windows Forms app. When an assertion fails, an assertion dialog is displayed. I'd like to be able to control when this dialog is displayed based on certain environmental conditions, but I don't want to have to change every call to Assert to account for this. Is this possible?

A As with any programming challenge, there are most likely multiple ways to solve this problem. One solution which works well is to write your own trace listener which derives from DefaultTraceListener. Override its Fail method and in your implementation only call to the base method when you want to allow the assertion to be displayed. Remember that the DefaultTraceListener implementation already only displays the dialog if the calling code has the UIPermissionWindow.SafeSubWindows permission and if the AssertUIEnabled setting is true in the application's diagnostics configuration. Once you have your custom trace listener, you can remove the DefaultTraceListener and substitute yours in its place. You can do it programmatically, like so:
System.Diagnostics.Debug.Listeners.Clear();
System.Diagnostics.Debug.Listeners.Add(new MyCustomTraceListener());
Or you can use a configuration file, as shown here:
<system.diagnostics>
    <trace autoflush="true" indentsize="0">
        <listeners>
            <clear/>
            <add name="MyTraceListener" 
                type="NetMatters.MyCustomTraceListener, MyAssembly" />
        </listeners>
    </trace>
</system.diagnostics>
A As with any programming challenge, there are most likely multiple ways to solve this problem. One solution which works well is to write your own trace listener which derives from DefaultTraceListener. Override its Fail method and in your implementation only call to the base method when you want to allow the assertion to be displayed. Remember that the DefaultTraceListener implementation already only displays the dialog if the calling code has the UIPermissionWindow.SafeSubWindows permission and if the AssertUIEnabled setting is true in the application's diagnostics configuration. Once you have your custom trace listener, you can remove the DefaultTraceListener and substitute yours in its place. You can do it programmatically, like so:
System.Diagnostics.Debug.Listeners.Clear();
System.Diagnostics.Debug.Listeners.Add(new MyCustomTraceListener());
Or you can use a configuration file, as shown here:
<system.diagnostics>
    <trace autoflush="true" indentsize="0">
        <listeners>
            <clear/>
            <add name="MyTraceListener" 
                type="NetMatters.MyCustomTraceListener, MyAssembly" />
        </listeners>
    </trace>
</system.diagnostics>
If you decide to take another approach and want to be able to display the assertion dialog at will without relying on the Debug or TraceListeners collection, an easy way is to again use the functionality built into the DefaultTraceListener:
new DefaultTraceListener().Fail();
This will display the assertion regardless of which listeners are currently configured in the listeners collections. Remember, too, that referring to the Debug and Trace listeners collections as separate entities is a bit of a misnomer. Internally, both Debug.Listeners and Trace.Listeners wrap TraceInternal.Listeners, and thus a listener added to one of them is actually added to both. In fact, the real difference between the Trace and Debug classes is the value passed as a parameter to the ConditionalAttribute attached to each method on the classes. This attribute controls the circumstances under which the call sites are compiled into the target Microsoft intermediate language (MSIL).

Q For my application, I need a buffer that only keeps the last n objects added to it. I checked the System.Collections namespace but I couldn't find anything appropriate. Does such a class exist? Is there any way to reuse existing functionality in the .NET Framework to make my implementation easier?
Q For my application, I need a buffer that only keeps the last n objects added to it. I checked the System.Collections namespace but I couldn't find anything appropriate. Does such a class exist? Is there any way to reuse existing functionality in the .NET Framework to make my implementation easier?

A As far as I know, System.Collections.Queue is the closest class in the Framework to what you want. In fact, it's so close that with only a few added lines of code you can create your own class that behaves the way you require.
A As far as I know, System.Collections.Queue is the closest class in the Framework to what you want. In fact, it's so close that with only a few added lines of code you can create your own class that behaves the way you require.
The Queue class implements the classic First In First Out (FIFO) data structure of the same name. Internally, it maintains an array of objects and two integers that mark the head and tail positions within that array. When the Enqueue method is used to add an item to the queue, the internal capacity of the queue is checked to determine whether the array has enough room to store the new item. If it doesn't, the size of the array is increased. After it has confirmed there's enough room, the new item is added at the position specified in the tail integer. The tail integer is then incremented, possibly causing it to wrap around to the beginning of the array; this can happen if items have been dequeued, incrementing the head pointer and leaving a gap at the beginning.
In order to implement the circular buffer, all you need to do is ensure that there's a maximum capacity for the queue and that you never exceed that limit. One solution is to override the Enqueue method and first check to determine whether you've reached the limit. If you have, simply remove an item using the Dequeue method, then proceed by delegating to the base class. The code in Figure 4 shows the basics of the implementation. Note that in order to make this truly robust, you should override and implement other methods like Queue.Clone, which returns a Queue instance, but I'll leave that as an exercise for you.

Q I want to write a regular expression that will detect strings that have only legal combinations of '{' and '}' characters (where every '{' is at some point followed by a matching '}'), but I can't figure out how to express it. Is this even possible? For example, the string "abcd{1234{5678}ef}g" is valid, as is "{}", but "}{" and "abcd{1234{5678{ef}g}" are invalid. Help!
Q I want to write a regular expression that will detect strings that have only legal combinations of '{' and '}' characters (where every '{' is at some point followed by a matching '}'), but I can't figure out how to express it. Is this even possible? For example, the string "abcd{1234{5678}ef}g" is valid, as is "{}", but "}{" and "abcd{1234{5678{ef}g}" are invalid. Help!

A Matching all strings with equal numbers of '{' and '}', regardless of their order, requires a grammar more powerful than regular grammars (those that can be processed by regular expressions). It can easily be done with context-free grammars (CFG), but there are no classes in the Framework for parsing those.
A Matching all strings with equal numbers of '{' and '}', regardless of their order, requires a grammar more powerful than regular grammars (those that can be processed by regular expressions). It can easily be done with context-free grammars (CFG), but there are no classes in the Framework for parsing those.
If all you want to do is find out if there are legally matching '{' and '}' characters, you can write some simple code to walk through each character in the string and enforce the rule manually. Start with a count of 0. Every time you see a '{', increment the count by 1; every time you see a '}', decrement the count by 1. If you ever get a negative count at any step along the way, your string is not a match. If at the end the count equals 0, then it is a match:
private bool IsMatch(string str)
{
    int count=0;
    for(int i=0; i<str.Length; i++)
    {
        if (str[i] == '{') count++;
        else if (str[i] == '}') count--;
        if (count < 0) return false;
    }
    return count == 0;
}
Even if there were Framework classes that provided CFG support, you can't get much better performance than something like what I've just shown, and what you're doing should be clear to anyone maintaining the code (especially if you add comments).
[ Editor's Update - 7/20/2004: The System.Text.RegularExpressions.Regex class supports grouping constructs with lookahead and lookbehind modifiers. This allows it to support some grammars more powerful than regular grammars (for more information, see Grouping Constructs). As such, matching all strings with an equal number of properly-ordered left and right brackets is possible using a pattern like the following:
string pattern = 
    @"^((?<openBracket>\{) | [^\{\}] |" + 
    @"(?<closeBracket-openBracket>\}))*" +
    @"(?(openBracket)(?!))$";
Regex r = new Regex(pattern, RegexOptions.IgnorePatternWhitespace);
However, the IsMatch method shown previously will still perform better than this equivalent Regex.]

Q I'm writing an application that makes HTTP requests to various Web sites using the URLs provided to me by a user. I only want to make the request if the URL is on my local intranet. Is there an easy way to perform this check?
Q I'm writing an application that makes HTTP requests to various Web sites using the URLs provided to me by a user. I only want to make the request if the URL is on my local intranet. Is there an easy way to perform this check?

A The System.Security.Policy namespace provides a Zone class that is used by the common language runtime (CLR) when enforcing Code Access Security (CAS). You can explicitly use the Zone class to perform the desired check:
private static bool IsIntranet(Uri url)
{
    System.Security.Policy.Zone zone =
        System.Security.Policy.Zone.CreateFromUrl(url.ToString());
    return zone.SecurityZone == System.Security.SecurityZone.Intranet;
}
URL membership in a zone is based on your Internet Explorer configuration. To configure zones, use the Security tab in the Internet Explorer options panel.
A The System.Security.Policy namespace provides a Zone class that is used by the common language runtime (CLR) when enforcing Code Access Security (CAS). You can explicitly use the Zone class to perform the desired check:
private static bool IsIntranet(Uri url)
{
    System.Security.Policy.Zone zone =
        System.Security.Policy.Zone.CreateFromUrl(url.ToString());
    return zone.SecurityZone == System.Security.SecurityZone.Intranet;
}
URL membership in a zone is based on your Internet Explorer configuration. To configure zones, use the Security tab in the Internet Explorer options panel.
A safer approach might be to run the code that makes these requests in a CAS sandboxed environment that only allows requests to intranet URLs. You can read more about sandboxing at Sandboxing code dynamically.

Send your questions and comments to  netqa@microsoft.com.


Stephen Toub is the Technical Editor for MSDN Magazine.

Page view tracker