在上一篇文章中,为了解决成员访问级别的问题,我采用了一个object adapter,使得客户程序无法轻易地修改对象的属性。网友评论说,我的这种做法就是绕了一圈,的确,这种方法没办法阻止客户程序刻意地去修改对象的属性,但在一定程度上起到了保护作用:至少降低了误操作的可能性。

今天发现其实可以用System.Runtime.CompilerServices.InternalsVisibleToAttribute这个特性达到同样的效果。以下是操作步骤。

  1. 假设ExposedSetter.Library这个class library中包含了一个具有internal setter属性的SourcedAggregationRoot类。首先,对ExposedSetter.Library作数字签名。在ExposedSetter.Library项目上点右键选择“Properties”。在“Signing”页下选择“Sign the assembly”选项,然后指定一个强名称密钥文件。SourcedAggregationRoot的代码以及ExposedSetter.Library的签名设置如下
    隐藏行号 复制代码 代码
    1. public class SourcedAggregationRoot : IVersionControllable
      
    2. {
      
    3.     private long version;
      
    4.     private long branch;
      
    5.     #region IVersionControllable Members
      
    6.     public long Version
      
    7.     {
      
    8.         get { return this.version; }
      
    9.         internal set { this.version = value; }
      
    10.     }
      
    11.     public long Branch
      
    12.     {
      
    13.         get { return this.branch; }
      
    14.         internal set { this.branch = value; }
      
    15.     }
      
    16.     #endregion
      
    17. 
      
    18.     public override string ToString()
      
    19.     {
      
    20.         return string.Format("Version = {0}, Branch = {1}",
      
    21.             version, branch);
      
    22.     }
      
    23. }
      

     image

  2. 新建一个class library,以调用ExposedSetter.Library中SourcedAggregationRoot的internal setter属性。为方便描述,我们将这个class library命名为ExposedSetter.Library2。在这个class library上添加对ExposedSetter.Library的引用,同时随便写一个测试的类,在类里直接调用SourcedAggregationRoot的internal setter属性来设置属性值。
    隐藏行号 复制代码 代码
    1. public class Class1
      
    2. {
      
    3.     public SourcedAggregationRoot Test()
      
    4.     {
      
    5.         SourcedAggregationRoot sar = new SourcedAggregationRoot();
      
    6.         sar.Branch = 125;
      
    7.         return sar;
      
    8.     }
      
    9. }
      

    同样,为ExposedSetter.Library2做数字签名(这一点很重要!)

  3. 启动Visual Studio的Command Line,使用sn.exe获得ExposedSetter.Library2的公共密钥(public key),注意:是public key,而不是public key token
    image
  4. 打开ExposedSetter.Library的AssemblyInfo.cs文件,向其添加InternalsVisibleToAttribute:
    隐藏行号 复制代码 代码
    1. [assembly: InternalsVisibleTo("ExposedSetter.Library2, PublicKey=0024000004800000940000000602000000240" +
      
    2.     "000525341310004000001000100bbccb249a2e7a1" +
      
    3. "7cbddf86e24532777568cb13c2ea7643b61cf60367068f2b9ca785dca303c49f015823e4eaa17b" +
      
    4. "50ed60ac47563dc8d8771358f10c3dc41f288530cfa350e6a2a24781dedeb8ec4138f93e76c537" +
      
    5. "bce6c5aa7b25858fa90d6ef5c6ea613b1b49e6e287f9ebb7f990cfa0ce17fbfe1c338e95e88c14" +
      
    6. "81f9598f")]
      

    注意,InternalsVisibleToAttribute的参数指定了允许访问其internal成员的assembly名称和公共密钥数据。在此不能设置assembly的版本等信息,否则编译都过不去。

  5. 编译解决方案

这种方式有点像C++的友元。与我上文提到的引入object adapter的解决方案相比,这种做法更加professional一些,毕竟可以通过.NET Framework直接支持,而且也更加安全一些,它能够明确指定哪些assembly可以访问,其余的则不能访问。但这种做法也有弊端:假设我今后又有一个assembly希望使用ExposedSetter.Library中的internal成员,我需要去修改ExposedSetter.Library中的代码,以添加一个InteralsVisibleToAttribute特性。

 

转帖地址:http://www.cnblogs.com/daxnet/archive/2010/08/12/1797782.html

posted @ 2010-08-12 09:24 JV Studio 阅读(40) 评论(0) 编辑

  几个月来,疑被SOA,一直在和XML操作打交道,SQL差不多又忘光了。现在已经知道,至少有四种常用人XML数据操作方式(好像Java差不多),不过还没有实际比较过这些方式各有哪些特点或优劣。正好看到网上也没有这方面的实验,偶来总结一下。

  测试开始先读取XML源,用一个比较大的RSS文件链接,复制到项目bin/debug目录下。

Stream xmlStream = new MemoryStream(File.ReadAllBytes(path));

    

  一、XmlDocument 方式

代码

 

  二、XPathNavigator 方式

代码
1 static IList testXmlNavigator()
2 {
3 var doc = new XmlDocument();
4 doc.Load(xmlStream);
5 var nav = doc.CreateNavigator();
6 nav.MoveToRoot();
7 var nodeList = nav.Select("/channel/item");
8 var lstChannel = new List<Object>(nodeList.Count);
9 foreach (XPathNavigator node in nodeList)
10 {
11 var channel = new
12 {
13 Title = node.SelectSingleNode("title").Value,
14 Link = node.SelectSingleNode("link").Value,
15 Description = node.SelectSingleNode("description").Value,
16 Content = node.SelectSingleNode("content").Value,
17 PubDate = node.SelectSingleNode("pubDate").Value,
18 Author = node.SelectSingleNode("author").Value,
19 Category = node.SelectSingleNode("category").Value
20 };
21 lstChannel.Add(channel);
22 }
23 return lstChannel;
24 }

 

  三、XmlTextReader 方式

代码

 

  四、Linq to XML 方式

代码

 

  测试结果:

XmlDocment 47ms
XPathNavigator 42ms
XmlTextReader 23ms
Xml Linq 28ms

 

  小结一下自己的认识,XmlDocument的操作基本按W3C的DOM操作方式,不过要将全部节点解析成对象加载到内存中,往往造成很大浪费。所以微软自己的编程规范也不推荐用它。这里由于读取了所有节点,可能因此性能和Navigator方式相差不大。在三种随机读取方式中,Xml Linq性能最高,只是方法名有点别扭。XmlTextReader方式是所谓的SAX,只读向前,无疑性能最高,不过实现上麻烦了不少,要比较精确的控制访问逻辑,也无法用匿名类存储数据。

  .Net 3.5发布Xml Linq可以很好地取代前两种方式,通常情况下,最好用它。只有个别场合,如果对性能要求极高,或者读取Xml数据量太大不能一下子下载或读取到内存中,那就只好痛苦委身于XmlTextReader了。

 

转帖地址:http://www.cnblogs.com/XmNotes/archive/2010/08/12/1796162.html

posted @ 2010-08-12 09:19 JV Studio 阅读(21) 评论(0) 编辑