分类: C/C++
2008-04-01 20:28:53
我想从某个方法中使用该方法的 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; } ... }
C#的编译器可以直接从C#的源代码文件中提取其XML注释。如果在编译时,/doc 命令行选项(或Visual Studio .NET IDE 中同等选项),被用于指定一个文档目标文件,那么源代码中的所有注释将会被提取出来并按 XML 格式写入该目标文件中。 当这个 XML 文件与编译过的程序集在同一目录时(注意:这个 XML 文档还必须与程序集同名,但扩展名为 .XML),Visual Studio .NET 便能用这个文件显示(IntelliSense:“智能感应”)。到 Visual Studio 2005 推出时,Visual C++ 与 Visual Basic 的编译器都能支持这个特性。
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 )。
我想在运行时访问一个 COM 组件,但我没有对应的 interop 程序集。我还能使用它吗?我曾考虑在需要时动态生成一个程序集,但这 样做似乎有些过度。问题是我正在编写一个.NET的通用工具类,在编译时不知道该 COM 组件的 ProgID。而这个组件实现了 IDispatch 接口。
Type 类提供了一个方法 GetTypeFromProgID(),正好适用于你的这种情形 (如果你只知道 CLSID,而不是 ProgID,可以用 Type.GetTypeFromCLSID())。将 COM 组件的 ProgID 作为参数调用该方法,它将返回描述该组件的一个 Type 对象。接着利用 Activator 类创建该组件的一个实例,再通过 Type 类的各种方法 (比如 InvokeMember、SetProperty 与 GetProperty)访问这个实例。using(LateBoundComHelper lb =
new LateBoundComHelper("SharePoint.StssyncHandler"))
{
string stsSyncHandler = (string)lb.Invoke("GetStssyncAppName");
}
如果你的系统上安装了Microsoft Outlook 2003,那么在 stsSyncHandler 最可能返回的应该是“Outlook”。
我们的开发团队在整个 Windows Forms 程序中使用了 Debug.Assert。当有一个断言失败时,就会 显示一个断言对话框。我想根据某种环境条件来控制该对话框的显示,让它只在某些特定的环境条件下才被显示,但又不想为此去修改每次对 Assert 的调用。这能做到吗?
如同任何一个编程挑战一样,对这个问题也有多种解决办法。一个可行的方案是从 DefaultTraceListener 派生 来编写自己的跟踪侦听器(Trace Listener)。重写其 Fail()方法,并且只在需要显示断言对话框的地方才调用基类的 Fail()方法。记住,只有在调用代码有UIPermissionWindow.SafeSubWindows 权限,并且在程序的诊断配置中启用了 AssertUIEnabled 设置,DefaultTraceListener 才会显示断言对话框。如果你自定义了跟踪侦听器,你可以 象下面这样编程实现替换 DefaultTraceListener: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 =
@"^((?\{) | [^\{\}] |" +
@"(?\}))*" +
@"(?(openBracket)(?!))$";
Regex r = new Regex(pattern, RegexOptions.IgnorePatternWhitespace);
不管怎样,前面展示的 IsMatch 方法仍然比等价的 Regex 表现要好。]
我正在编写一个应用程序,它使用 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 杂志的技术编辑。