.NET MATTERS ... XML annotation, late binding COM and other original: Stephen Toub translation: Abbey Download Source: Netmatters0406.exe (173KB) Original Source: .NET MATTERS: XML Comments, Late-Bound COM, And More MSDN Magazine June 2004) Note: This article is updated in MSDN magazine. This article also gives a given. See: Edit Update. For more information on updates, please refer to the original text. I want to use the XML documentation of this method from a method, this is possible? I hope to use them in the following way: ///
Public static void main (string [] args)
{
IF (args.length == 0)
{
Console.writeLine (Xmlcomments.current.summary.innertext);
Return;
}
...
}
Is there such a class within the .NET frame? The C # compiler can extract its XML annotation directly from the source code file of the C #. If you are compiled, the / doc command line option (or the same option in Visual Studio .NET IDE) is used to specify a document destination file, all comments in the source code will be extracted and written according to XML format. Target files. When this XML file is set in the same directory with the compiled assembly (Note: This XML document must be with the same name, but the extension is .xml), Visual Studio .NET can use this file display (IntelliSense: "smart induction"). When Visual Studio 2005 is launched, Visual C compilers with Visual Basic support this feature. The .NET framework does not provide classes that are specifically used to collect and process XML annotations, but the functionality provided by System.xml namespace can be used directly to complete such tasks. In fact, there is a class in the source code included in this article, with this class, you can use the syntax you described above. To get an XML document describing a specific type or class member, you first have to find the XML file containing that document. To do this, you must know which program or class member is declared in the set of (the element in the XML document is closely related to these elements in the assembly, see the source file, then look at the generated XML file understood). For a given MEMBERINFO object, you can call MEMBERINFO.DECLARINGTYPE () to get the TYPE object that declares the member (if you want to describe a Type document, you don't have to get its declaringType, because you already have a valid Type object ). Use this Type object to find the assembly declared this type, then, the Assembly instance returned from the property reveals the location of the file on the disk via the Location property. Then, you can use the .xml replace the extension of the assembly file and load this XML document from its location into the XMLDocument object. It should be noted that most of the .NET framework is loaded from the GAC (global assembly cache -global assembly cache), while its XML document file is running at runtime directories. If the system is loaded with the XML document from the folder directory of the assembly, try the location returned from the RuntimeNVironment.GetruntiMedIRectory () method (see the previous column). Figure 1 Programming Implementation to XML Comments Once you load the XML annotation of the assembly to an XMLDocument object, you can use the XPath expression to find a comment describing a specific MemberInfo object. Its principles such as Figure 1. For the code examples of XMLNode, see Figure 2. For how to create an XPath expression based on XML documents, see Processing The XML File. I have created an XMLComments class that constructs a MemberInfo object as a parameter, which is the XML annotation you want. This constructor acquires XMLNODE to get a note (if any), and use the XPath query parsing node and describe the summary, method parameters, and the exceptions that can be throwd out.
These nodes and node lists are then obtained through the public properties of XMLComments, such as: Summary and Exceptions. In order to solve the problem you have filed, I added a static revent property that uses the StackTrace class to get the method calling frame, and then use the associated MemberInfo to construct an XMLComments instance. Public static xmlcomments current {
Get {return new xmlcomments (new stacktrace (). getframe (1) .getMethod ());
}
I have encountered some problems when I wrote this thing, and the most important one is the accessor method for the attribute and event. The accessor does not have its own XML annotation, so for a given accessor MethodInfo, I need to access his father MethodInfo. One way is to use simple string processing from the accessory name (for example, the start portion "GET_" or "SET_") of the Trims Accessor Name). I have chosen a simple and practical method. For a given type, I use a hash table to store the mapping of the MethodInfo object to their parenting MEMBERINFO (created by traversing all attributes and events in a Type object, and find all the accessible access) Add to this table). When you need to check if a method is an accesser, I can query this table; if the MemberInfo is a table key value, then I can not only definitely be an accessory, but also immediately access his parent classes. MEMBERINFO, and passed it as a parameter to getcomments () method, as shown in Figure 2, replacing the original MethodInfo of the accessor). Of course, the above solution applies only to generate XML comments for your own application. And it is necessary to keep the XML annotation is not compiled into the assembly, but in the form of an independent .xml file, that is, any solution that uses the technology should be tested whether the .xml file exists, whether it is in the correct position Have you namdooted properly. I want to visit a COM component at runtime, but I have no corresponding interope assembly. Can I still use it? I have considered to generate an assembly when I need it, but this seems to be excessive. The problem is that I am writing a generic tool class of .NET, do not know the ProgID of the COM component upon compile. This component implements the IDispatch interface. The Type class provides a method gettypefromProgid (), just applies to this situation (if you only know CLSID, not ProgID, you can use Type.gettypeFromClsid ()). Call the ProgID of the COM component as a parameter, which will return a TYPE object description of the component. This instance is then created using an instance of the component using the Activator class, and then accesses this instance through various methods of the Type class (such as InvokeMember, SetProperty and getProperty). In order to make the above work easier, I created an auxiliary class, as shown in Figure 3, simplified common operations. Consider the following example, the code creates an instance of a COM component SharePoint.StssyncHandler, and queries its GetStssyncAppName method to determine which program is processed on the machine stssync protocols: using (LateBoundComHelper lb = new LateBoundComHelper ( "SharePoint.StssyncHandler") )
{
String stssynchandler = (string) lb.invoke ("getstssyncAppname);
}
If you have Microsoft Outlook 2003 on your system, you should be "Outlook" at StsSyncHandler's most likely returned. On the other hand, a similar auxiliary class is also hidden in the system.Web namespace of the .NET framework. Use your most familiar anti-compile or disassembly tools to find the System.Web.mail.Smtpmail class. This SMTPMAIL class embedded a LateBoundAccesshelper class, which provided a late-bound access to cdont.newmail in Windows NT, CDO.Message in Windows 2000 or later. If you still need to use a COM component's type library to dynamically create an assembly, you can implement it by calling the System.Runtime.InterOpServices.TypeLibConvertoAssembly () method. In fact, the tool TLBIMP.EXE and TLBEXP.EXE in the .NET Framework SDK are implemented by encapsulated this class (Tlbimp.exe uses the ConvertTypeLibtoAssembly () method, and TLBexp.exe uses the convertassemblytotypelib () method). See TypelibToAssembly Method for details on this method. Our development team uses Debug.Assert in the entire Windows Forms program. An assertion dialog is displayed when there is an assertion failure. I want to control the display of the dialog in accordance with some environmental conditions, so that it is only displayed under certain environmental conditions, but does not want to modify the call to Assert every time. Can this do it? Like any programming challenge, there are a variety of solutions to this issue. A feasible solution is to derive from DefaultTracelistener to write your own tracking listener. Rewinding its fail () method and only the FAIL () method of the base class is called only when the assertion dialog is required. Remember, only if the code has UIPERMISSIONWINDOW.SAFESUBWINDOWINDOW.SAFESUBWINDOWINDOWINDOW.SAFESUBWINDOWS, and the AssertuieNabled settings are enabled in the diagnostic configuration of the program, DefaultTraceListener displays the assertory dialog. If you customize the tracking listener, you can implement the replacement of DEFAULTTRACELISTENER: System.DiagnostCEBUG.LISTENERS.ADD (New MycustomTraceListener ()); or use A configuration file like this:
TYPE = "Netmatters.mycustomtracelistener, myassembly" /> listeners> trace> If you decide to use additional methods and want to rely on Debug or TraceListener collection when displaying the assertion dialog, then a simple way is to use the DEFAULTTRACELISTENER's built-in function: new defaultTracelistener (). Fail (); no matter Which listeners currently configured in the listener collection will display this assertion. Also remember: The collection of DEBUG and TRACE is not appropriate to be a separate entity idea. In fact, both of DEBUG.LISTENERS and TRACE.Listeners have both TRACEINTERNAL.Listeners inside, so the listener is added to another collection, and it is also added to another collection. In fact, the true difference between the Trace and the DEBUG class is the value transmitted to the ConditionaAttribute as a parameter to each method attached to the class. This feature controls the environment that calls the site to be compiled into the target MS intermediate language (MSIL). My program needs to save the last added n objects in a buffer. I have not found the appropriate class in the entire System.Collections namespace. Is there such a ready-made class? Is there a way to reuse the ready-made features in the .NET framework makes my implementation simple? As far as I know, System.Collections.Queue is the class closest to your requirements in the .NET framework. In fact, just add a few lines of code, you can make it completely in line with your requirements and complete your required operations. The Queue class implements the classic data structure with the same name as FIRST IN First Out, advanced first out. Inside it, it maintains an object array and two integers for indicating the number of array heads. When the ENQUE () method adds an element to the queue, it first checks to determine if an array has enough space to accommodate new elements. If you can't, the capacity of the array will be added. When confirming that an array has enough space, the new element will be added to the tail position specified by the integer. With the growth of the tail integer, it may cause it to incorporate the starting position of the array, because the element is increasing after the team, thereby leaving an gap in the starting position of the array. (Translation: System.Collections.Queue class uses an annular array, should there be such a "fake overflow" phenomenon?). In order to achieve ring buffering, you must ensure that the queue has the largest capacity and must not exceed this maximum upper limit. (Translation: About the ring buffer, there is a piece of CodeProject, I spent an hour, I didn't open it. :-P). One solution is to change the enqueue () method, first detect if the quantity of the quantity has been reached. If so, simply call the demue () method to delete an element, then the base class will continue to execute. The code in Figure 4 shows the basic implementation. Note that in order to make the code more robust, you also need some other ways to rewrite and implement, such as Queue.clone, it returns a queue instance, I will leave it as a practice to you. I want to write a regular expression that scans only a string that matches only the "{" and "}" character combination ("{" follows the "}"), but I can't determine the expression. Is it possible to implement? For example, the string "ABCD {1234 {5678} EF} G" is valid because "{}", and "} {" and "ABCD {1234 {5678 {EF} G}" are invalid. Seeking help! Match the entire string with "{" and "}" with quantity, regardless of the order of them, there is a more powerful syntax (those that can be processed by regular expressions), with CFG (Context-Free Grammars can be easily resolved. However, there is no corresponding parsing class in the .NET framework. If you just want to determine if there is a legal match with the "{" and "}" characters, you can write some simple code to traverse it in the string, there is no character in the string and to hold this rule manually. The count starts at 0, and each time the "{" timer is added 1, each time a "}" is reduced. This is when it traverses the entire string, if the counter is negative, then this string is not matched. If the counter is 0, the string is matched. Private Bool Ismatch (String Str) { INT count = 0; For (int i = 0; i { IF (STR [I] == '' {') count ; ELSE IF (STR [I] == ''} ') count -; IF (count <0) Return False; } Return count == 0; } Even if you have a CFG class that supports the .NET framework, I think it is better than my demonstration code, and it is clear that it is very clear for anyone who maintains the code (especially the comment). [Edit Update-7/20/2004: System.Text.RegularExpressions.Regex supports the use of Lookahead and LookBehind modifiers group constructs, so support more powerful syntax than regular syntax (see details on this: "GROUPING Constructs "). Therefore, the possible mode of the left and right ocul arc matching strings that are equal to the appropriate rules are as follows: string pattern = @ "^ ((? @ "(? @ "(? (?!)) $"; Regex R = New Regex (Pattern, RegexOptions.ignorepatternwhitespace); In any case, the ismatch method shown in front is still better than the equivalent regex performance. ] I am writing an application that uses HTTP requests the user's Different web sites URLS addresses. But I just want to ask the URL in the local intranet. Is there any simple way to implement this check? When enforcing the CAS (Code Access Security) mechanism, system.security.policy namespace provides a Zone class that is running (CLR) by the public language (CLR). You can explicitly use the ZONE class to implement the kind of check you want. Private Static Bool IsInet (URI URL) { System.security.policy.zone zone = System.security.policy.zone.createFromurl (Url.toString ()); Return zone.securityzone == system.security.securityzone.Inet;} The URL member relationship in a region is based on your IE configuration. In order to configure the region, use the Security tab in the IE panel. A more secure approach is to run these HTTP request code in a CAS sandbox environment that allows IntraNet Urls. For details on the sandbox, please see Sandboxing Code Dynamically (I can't access the web page). If you have any questions or opinions, please send me email: Netqa@microsoft.com.stephen Toub is the technical editor of MSDN magazine. From MSDN Magazine, June 2004. This magazine can be purchased through newsstands from all over the country or subscribe.