孙展波:实现.NET无限潜力

Realize .NET Potential (中文版)
随笔 - 430, 评论 - 12203, 引用 - 54

导航

关于

贴子以"现状"提供且没有任何担保也没有授予任何权利。
计数器(2005/12/8起).点击阅读我的Blog In English

标签

每月存档

最新留言

广告

【第1页/共2页,20条】
首页
前页
1

在Visual Studio 2008中使用Microsoft Reference源代码服务

先前相关:微软将发布.NET框架库的大量源代码

在上次Blog的评论中,有人称赞道:确实,调试方便了不是一点点;这真是太cool了;很好,期待很久了!不过也有这样的评论:买一张MSDN就可以了。实际上,MSDN中并没有包含将发布的.NET Framework的源代码。

这项服务还在最后的调试阶段,很快就会对外发布。我在这个周末通过Visual Studio 2008使用了这一服务。对于.NET程序员来说,这真的是非常有助于调试,也提供了软件开发时候很有价值的参考。

为了在Visual Studio 2008中使用此服务,有以下几个要点:

  1. 在Debugging | General 选项中,不要选Enable Just My Code (Managed Only).
  2. 在Debugging | General 选项中,选择Enable source server support.
  3. 在Debugging | Symbols 选项中,添加Microsoft Reference源代码服务的URL。 正式的URL很快会对外发布。

首次使用时需要接受2个License:一个是symbol,另外一个是Source.

这样在调试程序的时候就可以看到.NET Framework的源代码,也可以在调试时跟进(Step into)。

比如说WinForm的Button.cs就被下载到\src\source\.net\8.0\DEVDIV\depot\DevDiv\releases\whidbey\REDBITS\ndp\fx\src\WinForms\Managed\System\WinForms\Button.cs\1\Button.cs。从文件夹的结构可以看到,.NET框架3.5下的WinForm代码实质上还是Whidbey即.NET 2.0。但的确有了一些更新。REDBITS下是.NET 3.5发布时候的代码。

即使将Winform的项目的Target Framework改成2.0或者3.0,我们一样得到上述的Button.cs. 这是因为REDBITS在安装时取代了早先2.0的程序集。

在WPF下的Button.cs被下载到\src\source\.net\8.0\WIN_WINDOWS\lh_tools_devdiv_wpf\Windows\wcp\Framework\System\Windows\Controls\Button.cs\1\Button.cs。虽然现在WPF属于DevDiv的一部分了,从这个文件夹的结构可以看到以前WPF是隶属于Windows的。

在代码的格式上,您也一定能够看出DevDiv和Windows的区别。

除了在文件中添加了几行版权声明:

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

您看到的代码与微软内部能够看到的代码是完全相同的。那些代码中的注释,还有对private或者internal members的说明,都是在此之前无法从MSDN的文档中得到的信息。

当然没有任何代码是十全十美的。我已经注意到标有HACK HACK HACK注释的代码了。

阅读代码对程序员而言是一件有趣的活动。随着Microsoft Reference源代码服务的推出,我们有更多的阅读材料了!

posted on 2008-01-07 10:31:00 by zhanbos  评论(17) 阅读(7253)

微软将发布.NET框架库的大量源代码

伴随着Visual Studio 2008的发布,微软将在Microsoft Reference License规则下发布.NET框架库的大量源代码。这意味着只要您接受了许可条款,您就可以浏览这些源代码,而且,Visual Studio 2008的Standard edition和更高版本还支持在调试时跟进(Step into).NET源码。

首批发布的源代码包括BCL (System, IO, Text, Collections, CodeDom, Regular Expression等), ASP.NET, WinForms和WPF。

更多细节,将在最近的blog中讨论,

posted on 2007-10-04 00:18:00 by zhanbos  评论(11) 阅读(7349)

Q&A: 每一个KeyDown事件都保证有一个对应的KeyUp事件么?

问:在.NET框架函数库中, 是否每一个KeyDown事件都有保证一个对应的KeyUp事件?

答:不是,因为WinForm底层的Windows 32 Messages WM_KEYDOWN和WM_KEYUP并不能保证这一点,而WinForm所作的就是将其转化为对应的事件。

这一回答也适用于WPF中的对应事件。

posted on 2006-08-19 11:07:00 by zhanbos  评论(12) 阅读(7340)

细节,您注意到了么(7): UriFormatException的Message

以下这行代码

Uri uri1 = new Uri("pack://application:,,,", UriKind.Absolute);

会导致UriFormatException。其Message是:Invalid URI: A port was expected because of there is a colon (':') present but the port could not be parsed.

Message的文法是有问题的:because of应该是because. 搜索的结果表明有这样错误用法的例子还是颇有一些的。

posted on 2005-12-20 06:31:00 by zhanbos  评论(27) 阅读(7291)

.NET 2.0: 类型转递(Type Forwarding)

Type Forwarding指的是:.NET运行时将对某一个程序集(Assembly)之中定义类型的引用转递为对另外一个或者几个(更新的)Assembly之中同样类型的引用。

通过Type forwarding,所有引用(Reference)了Original程序集的程序会去引用新的程序集。

下面让我们通过实例演示Type Forwarding的使用

首先,创建显示Tech Ed 2005北京开始日期的一个简单类.将文件存为TechEd2005.cs.

using System;
namespace Microsoft.Tech.Ed
{
    public static class China
    {
        public static DateTime GetBeijingStartDate()
        {
            return new DateTime(2005, 9, 23);
        }
    }
}

编译第一个Assembly: csc /t:library Teched2005.cs,生成的Assembly就叫作TechEd2005.dll.

然后我们写一个Console Application打印出日期来。将以下代码存为reminder.cs

using System;
namespace Realize.Net.Potential
{
    public class Demo
    {
        public static void Main()
        {
            Console.WriteLine("Mark the date: " + Microsoft.Tech.Ed.China.GetBeijingStartDate().ToLongDateString());
        }
    }
}

编译reminder.cs: csc /t:exe /r:Teched2005.dll reminder.cs

运行reminder.exe就可以看到:Mark the date: Friday, September 23, 2005

但是不知不觉就到2006年了。我们需要推出新的Tech Ed日期了。假定Tech Ed 2006北京的开始日期为9月21日星期四,我们有新文件TechEd2006.cs如下

using System;
namespace Microsoft.Tech.Ed
{
    public static class China
    {
        public static DateTime GetBeijingStartDate()
        {
            return new DateTime(2006, 9, 21);
        }
    }
}
    

编译产生TechEd2006.dll: csc /t:lib Teched2006.cs

只是reminder.exe还是打印出2005年的日期。我们使用Type Forwarding解决更新类型之实现的功用。修改TechEd2005.cs成为

using System;
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.Tech.Ed.China))]
namespace Microsoft.Tech.Ed
{
}    

注意:TechEd2005.cs中原先的实现已经被删除。重新编译TechEd2005.cs,这一次需要引用TechEd2006.dll: csc /t:library /r:teched2006.dll TechEd2005.cs

再次运行reminder.exe,就可以看到:Mark the date: Thursday, September 21, 2006

重复一下要点:第一个(旧的)Assembly需要重新编译以使用TypeForwardedTo属性,但是新的Assemby和引用旧Assembly的Reminder.exe不需要重新编译。其对Microsoft.Tech.Ed.China的引用被CLR Runtime自动转递到新的Assembly上。旧的和新的assemblies须同时存在。

TypeForwardedTo只能用于Assembly。

posted on 2005-12-03 15:03:00 by zhanbos  评论(23) 阅读(8563)

Directory.GetFiles之searchPattern一问

正确回答此问题说明您对Directory.GetFiles之中的searchPattern的使用有较深的认识。

假定在path之中有且仅有3个文件。其文件名分别是Blog.h, Blog.htm和Blog.html。试试看,您能不能正确得到下面3句指令的输出。

Console.WriteLine(System.IO.Directory.GetFiles(path, "Blog*.h").Length);
Console.WriteLine(System.IO.Directory.GetFiles(path, "Blog*.htm").Length);
Console.WriteLine(System.IO.Directory.GetFiles(path, "Blog*.html").Length);

在命令行下使用DIR命令可以得到相似的结果。您可以参考MSDN文档

posted on 2005-11-27 13:11:00 by zhanbos  评论(16) 阅读(10255)

.NET 2.0: System.ComponentModel.INotifyPropertyChanged

INotifyPropertyChanged是在WPF项目中先提出并被其数据绑定引擎使用。最初的名字叫做IPropertyChaged。这个Interface的设计思想是:当一个objectpublic 属性变化时能通过PropertyChanged这个event的方式告知其他对象。

 

后来被.NET FCL收入,在程序集System之中定义,名称空间为System.ComponentModel.

 

INotifyPropertyChanged定义的唯一成员为PropertyChanged事件。以下为一个典型实现之示例:

 

public class TechEdCity : System.ComponentModel.INotifyPropertyChanged

{

    public TechEdCity(string name, DateTime startDate, DateTime endDate)

    {

        this.name = name;

        this.startDate = startDate;

        this.endDate = endDate;

    }

 

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

 

    public string Name

    {

        get

        {

            return name;

        }

        set

        {

            if (value != name)

            {

                name = value;

                RaisePropertyChangedEvent("Name");

            }

        }

    }

 

    public DateTime StartDate

    {

        get

        {

            return startDate;

        }

        set

        {

            if (value != startDate)

            {

                startDate = value;

                RaisePropertyChangedEvent("StartDate");

            }

        }

    }

 

    public DateTime EndDate

    {

        get

        {

            return endDate;

        }

        set

        {

            if (value != endDate)

            {

                endDate = value;

                RaisePropertyChangedEvent("EndDate");

            }

        }

    }

 

    private void RaisePropertyChangedEvent(string propertyName)

    {

        if (PropertyChanged != null)

        {

            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

        }

    }

 

    private string name;

    private DateTime startDate;

    private DateTime endDate;

}

 

posted on 2005-11-06 15:30:00 by zhanbos  评论(11) 阅读(5288)

.NET 2.0: 类ProcessStartInfo增加UserName和Password属性

在.NET 1.x之中,当需要以不同的Credential运行新的Process时,代码需要通过P/Invoke使用CreateProcessWithLogonW来实现。

在2.0下,System.Diagnostics.ProcessStartInfo类增加了UserName(类型为String)和Password(类型为SecureString)这2个属性,从而简化了这一操作。

 

posted on 2005-10-27 09:24:00 by zhanbos  评论(19) 阅读(5175)

答复lh提出的提供用户名和密码的方法之问题

lh在XAML之3D动画的一个演示下提出了一个并不相关的问题如下:

请问展波兄,
.NET中如何实现将文件a拷贝到不在同一域的目标文件夹内?
也即如何在代码中提供用户名和密码,来让文件可以成功拷贝?

我的答复:.NET框架还没有提供这样的API,您需要使用P/Invoke调用Win32的API: NetUseAddNetUseDel.这2个API都在Netapi32.dll这个文件中提供。

对于P/Invoke的写法和例子,您可以参考http://pinvoke.net这个网站。比如说关于NetUseAdd的介绍就在http://pinvoke.net/default.aspx/netapi32/NetUseAdd.html这里。注意这是第三方的网站。

这个网站上并没有NetUseDel的介绍。以下代码供参考:

private const uint USE_NOFORCE = 0; private const uint USE_FORCE = 1; private const uint USE_LOTS_OF_FORCE = 2; [DllImport("NetApi32.dll", SetLastError=true, CharSet = CharSet.Auto)] public static extern uint NetUseDel( string UncServerName, string UseName, uint ForceCond );

贴子以"现状"提供且没有任何担保也没有授予任何权利

posted on 2005-10-22 12:22:00 by zhanbos  评论(17) 阅读(3985)

调用Object.GetHashCode的缺省实现

所有的.NET类都是基于System.Object类的。在Object中定义了返回值为int的虚函数GetHashCode。因为是虚函数,子类可以重写(override)GetHashCode以体现更合逻辑的算法。但是,重写后的GetHashCode可能会产生比较集中占用了Int32的狭窄区间的Hash Code(哈希值),使得更多的不同实例有着相同的值.

 

这样的实现一点也不违背长生Hash code的原则。在极端情形下即使所有的实例的哈希值都是相同的,这也是合法的算法。当然也是很差的算法。

 

Object.GetHashCode的缺省实现则有着很好的哈希值分布。在实践中人们常发现一个实例的Hash Code几乎可以有和这个实例有一一对应的关系。也就是说,这是一个很佳的哈希算法。

 

问题是,当GetHashCode被子类重写后,我们如何能够在需要的情形下调用Object.GetHashCode的缺省实现呢?答案是:

int System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(object o); 这是定义在程序集mscorlib之中的。

 

贴子以"现状"提供且没有任何担保也没有授予任何权利

posted on 2005-06-13 06:04:00 by zhanbos  评论(8) 阅读(3462)

.NET 2.0: Thread.Suspend和Thread.Resume被废弃(obsolete)

实例函数(Instance Method)Thread.SuspendThread.Resume2.0版本下被标为obsolete. 编译使用这2个函数的代码会得到warning. 当然在以后的.NET版本下可能就会是编译错误了。

 

其警告信息包含下列信息:Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. (请使用System.Threading中的其他类,如Monitor, Mutex, Event, Semaphore,以同步线程和保护资源。)

 

Thread.SuspendThread.Resume被废弃的主要原因是因为其使用很容易造成线程死锁(Deadlock)

 

静态函数(Static MethodThread.Sleep的使用在.NET 2.0下不受影响。

 

贴子以"现状"提供且没有任何担保也没有授予任何权利

posted on 2005-06-13 05:05:00 by zhanbos  评论(8) 阅读(4763)

.NET 2.0: 新增StringComparison枚举型

System.StringComparison用于String.CompareString.Equal的相关函数之中,对于常用的字符串比较操作,提供了更简便的支持。

 

其枚举值包括:CurrentCulture, CurrentCultureIgnoreCase, InvariantCulture, InvariantCultureIgnoreCase, Ordinal, 和OrdinalIgnoreCase.

 

2.0之前使用的代码如:

String.Compare(mimeType, "image/jpe", true, CultureInfo.InvariantCulture)

就可以写成:

String.Compare(mimeType, "image/jpe", StringComparison.InvariantCulture);

 

使用StringComparison,既便于理解,又避免出错。

posted on 2005-06-10 15:31:00 by zhanbos  评论(2) 阅读(3643)

Type类的Name, FullName和AssemblyQualifiedName

一个类型的FullName是能够在一个Assembly(程序集)里唯一限定的名字,所以至少要有名称空间(Namespace)的信息。而一个类型的AssemblyQualifiedName则还要唯一限定了Assembly的名字。

 

如果Type t = typeof(bool);Name, FullNameAssemblyQualifiedName分别是

Boolean

System.Boolean

System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

 

如果Type t = typeof(Nullable<bool>);呢?能不能设想其FullName会是什么样的?

 

你会注意到其FullNamebool类型显示的是AssemblyQualifiedName。不能只使用boolFullName,虽然System.Boolean是在其定义的assembly(即mscorlib)中唯一指定了此类型,在别的Assembly中也可能有另外一个类有着相同的FullName。所以,为了能够在一个Assembly中(也是mscorlib)唯一限定Nullable<bool>, bool必须使用AssemblyQualifiedName才正确。

 

如果Type t = typeof(Nullable<bool>);Name, FullNameAssemblyQualifiedName分别是:

 

Nullable`1

System.Nullable`1[[System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

System.Nullable`1[[System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

 

贴子以"现状"提供且没有任何担保也没有授予任何权利

posted on 2005-05-30 04:53:00 by zhanbos  评论(4) 阅读(4115)

博客堂2005年度第三篇:有奖问答,于晓松提供线索

今天的新年有奖问答题的线索是于晓松友情提供的,感谢晓松对我的Blog的大力支持!

 

问题:怎样用最简洁的代码判断一个字符串是否以标点符号结尾(中英文标点都算数)?即对于这样的一个函数请你填空:

    private bool DoQuizHappyNewYear(string testString)

    {

      return ______________________;

    }

使得当testString以标点符号结尾时此函数返回true而当testString不是以标点符号结尾时此函数返回false.

 

填空并有解释说明第一个给出最合适回答的朋友将得到Alienware Mousepad作为小纪念品。2005年一月由Grace代为发送。

 

如果您也想为有奖问答提供出题线索,我的联系方式可以在此处找到。

 

贴子以"现状"提供且没有任何担保也没有授予任何权利

posted on 2005-01-03 19:36:00 by zhanbos  评论(11) 阅读(2935)

有奖问答:继承了System.ValueType 的类型一定是数值类型(而不是引用类型)么?

已知一个TypeBaseTypeSystem.ValueType,请问这个Type一定是数值类型么?

 

需要有解释说明,第一个给出合适回答的朋友将得到Alienware Mousepad作为小纪念品。要在12月下旬才可以寄出。可能是我也可能请Grace代为发送。

 

贴子以"现状"提供且没有任何担保也没有授予任何权利

posted on 2004-11-16 15:14:00 by zhanbos  评论(22) 阅读(3086)

【第1页/共2页,20条】
首页
前页
1

Powered by: Joycode.MVC引擎 0.5.2.0