分类: C/C++
2008-04-23 21:52:21
.NET MATTERS...
XML注释、迟绑定 COM 及其它
原著:
翻译:
下载源代码:(173KB)
原文出处:(MSDN Magazine
June 2004)
注:此文在 MSDN 杂志上有更新。本文也一并给出。参见:。有关更新的详细信息请参照原文。
我想从某个方法中使用该方法的 XML 说明文档,这可能吗?我希望能以下面这样的方式使用它们:
///在 .NET 框架内部有这样的类吗?用法: myApp.exe file1.dat file2.dat … fileN.dat public static void Main(string [] args) { if (args.Length == 0) { Console.WriteLine(XmlComments.Current.Summary.InnerText); return; } ... }
public static XmlComments Current { get { return new XmlComments(new StackTrace().GetFrame(1).GetMethod()); } }在我写这个东西时遇到了一些难题,其中最重要的一个是属性与事件的存取器(Accessor)方法。存取器没有自己的 XML 注释,所以对于 某个给定的存取器 MethodInfo,我需要存取其父辈 MethodInfo。一种方法是使用简单的串处理从存取器名字解析出属性和事件名(例如,修剪存取器名字的开始部分“get_” 或者“set_”)。我选择了一种简单实用的方法。对于一给定的类型,我利用一张哈希表来存储存取器 MethodInfo 对象到其父辈 MemberInfo 的映射(通过遍历某个 Type 对象中的所有属性和事件来创建,并将所有找到的存取器添加到这张表中)。当需要检查某个方法是否为存取器时,我可以查询这张表;如果 该 MemberInfo 是一个表中键值,那么我不仅可以肯定它是一个存取器,而且还可以立即访问其父类的 MemberInfo,并将其作为参数传递给 GetComments() 方法,如 Figure 2 所示,从而替代该存取器原来的 MethodInfo )。
using(LateBoundComHelper lb = new LateBoundComHelper("SharePoint.StssyncHandler")) { string stsSyncHandler = (string)lb.Invoke("GetStssyncAppName"); }如果你的系统上安装了Microsoft Outlook 2003,那么在 stsSyncHandler 最可能返回的应该是“Outlook”。
System.Diagnostics.Debug.Listeners.Clear(); System.Diagnostics.Debug.Listeners.Add(new MyCustomTraceListener());或者使用一个象这样的配置文件:
如果你决定用另外的方法并且想在显示断言对话框时不依赖 Debug 或者 TraceListeners 集合,那么一个简便易行的方法就是再次使用 DefaultTraceListener 内建的功能:
new DefaultTraceListener().Fail();
不管在侦听器集合中当前配置了哪些侦听器都会显示这个断言。也请记住:将 Debug 与 Trace 的侦听器集合当做是单独的实体想法是不恰当的。其实,Debug.Listeners 与 Trace.Listeners
两者在内部都封装了TraceInternal.Listeners,因此侦听器被添加到其中某个集合实际上同时也被添加到另一个集合。事实上,Trace
和 Debug 类之间的真正差别是作为参数传递给 ConditionalAttribute
的值被附加给类的每一个方法。这个特性控制着调用现场被编译成目标 MS 中间语言( MSIL )的环境。
我的程序需要在某个缓冲区里保存最后加入的N个对象。我在整个 System.Collections 命名空间中也没能找到合适的类。
请问有没有这种现成的类?.NET 框架中有没有办法复用现成的功能使我的实现变得简单些?
据我所知,System.Collections.Queue 是.NET
框架中最接近于你的要求的类。实际上,仅需增加几行代码就能让它完全符合你的要求,完成你所需的操作。
Queue 类实现了经典的与 FIFO (First In First
Out,先进先出)同名的数据结构。在其内部,它维护着一个对象数组和两个用于指示数组头尾的整数。当调用 EnQueue() 方法向队列中增加元素时,它首先会
进行内部检查以确定数组是否有足够的空间容纳新元素。若不能,便会增加数组的容量。当确认数组有足够的空间后,新元素会被添加到由整数指定的尾部位置。随着
表示尾部整数的增长,可能会导致它包合数组的起始位置,这是因为元素在出队后,头指针会增加,从而在数组的起始位置留下一个缺口。(译注:System.Collections.Queue 类使用了环形数组,应该不会出现这样的"假溢出"现象吧?)。
为了实现环形缓冲,你必须要保证队列具备最大的容量,并且决不能超过这个最大值上限。(译注:关于环形缓冲,CodeProject 中有一文,我花了一个小时也没打开。:-P)。一种方案是
改写Enqueue()方法,首先检测是否已达队列容量上限。如果是,只需简单地调用 Dequeue() 方法删除一个元素,然后委托基类继续执行。Figure
4 中的代码展示了基本的实现。注意为了让上述代码更健壮,你还需要改写并实现的其它的一些方法,如 Queue.Clone,它返回一个 Queue 实例
,我把它作为练习留给你来完成。
我想写一个正则表达式,它能扫描只与“{”和“}”字符组合匹配的字符串(“{”后某处跟随匹配的“}”),但我无法确定表达方式。请问有可能实现吗?比如字符串“abcd{1234{5678}ef}g”是有效的,
因为有“{}”,而“}{”和“abcd{1234{5678{ef}g}”则是无效的。寻求帮助!
用数量相等的“{”和“}”匹配整个字符串,而不管它们出现的顺序,
需要一种比正则语法(那些能被正则表达式处理的)更强大的语法,用 CFG(context-free grammars)可以轻松解决。但是.NET 框架中没有提供
相应的解析类。
如果你只是想确定是否有与“{”和“}”字符的合法匹配,那可以写一些简单的代码来遍历串中的没一个字符并手工强制此规则。计数以 0 开始,每次遇到“{”时计数器就加 1,每遇到一个“}”则减1。这样当遍历完整个字符串后,如果计数器为负值,那这个字符串就是未匹配的。若计数器为0,则字符串就是匹配了的。
private bool IsMatch(string str) { int count=0; for(int i=0; i即便具备支持.NET 框架的 CFG 类,我想其性能也不会比我上面示范的代码好多少, 况且对任何维护该代码的人来说它也很清晰(尤其是加上注释的话)。
[-7/20/2004:System.Text.RegularExpressions.Regex 支持用 lookahead 和 lookbehind 修饰符分组构造,这样便支持比正则语法更强大的某些语法(有关这方面的详细信息参见:“”)。因此,用数量相等的按适当规则排列的左右大括弧匹配字符串可能的模式如下:string pattern = @"^((?不管怎样,前面展示的 IsMatch 方法仍然比等价的 Regex 表现要好。]\{) | [^\{\}] |" @"(? \}))*" @"(?(openBracket)(?!))$"; Regex r = new Regex(pattern, RegexOptions.IgnorePatternWhitespace);
我正在编写一个应用程序,它使用 HTTP 请求用户提供的不同 Web 站点的 URLs 地址。但我只想请求本地 Intranet 内的 URL。有没有什么简单易行的方法来实现这种检查?
当强制执行 CAS (Code Access Security)机制时,System.Security.Policy 命名空间提供了一个 由公共语言运行时(CLR)使用的 Zone 类。你可以显式地使用该 Zone 类来实现你所希望的那种检查。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 成员关系是基于你的 IE 配置的。为了对区域进行配置,使用 IE 选项面板中的“安全”标签页。
一个更安全的办法是在一个只允许请求 Intranet URLs 的 CAS 沙盒环境中运行这些 HTTP 请求代码。关于沙盒的详细内容,请参见 (译注:我无法访问该Web页)。
有什么疑问或者意见,请给我发Email:netqa@microsoft.com.
Stephen Toub 是 MSDN 杂志的技术编辑。