cast 的个人资料nonocast ! 真诚原是一种需要坚强不屈的...照片日志列表更多 工具 帮助
9月29日

foreach & ForEach support

并不是只有List<T>才有foreach/ForEach的权利,我们也同样很轻松的实现它
就像这样,

public class ForEachSupport {

       static void Main(string[] args) {

              Console.WriteLine("foreach & ForEach support");

             

              EnumerableClass<Document> ec = new      EnumerableClass<Document>();

              ec.link(Document.create("hello"));

              ec.link(Document.create("world"));

              ec.link(Document.create("!!!"));

             

              foreach(Document each in ec) {

                     Console.WriteLine(each.Title);

              }

             

              ec.ForEach(delegate(Document each){

                     Console.WriteLine(each.Title);

              });

             

              Console.ReadLine();

       }

}

 

实现也很简单,

 

public class EnumerableClass<T> : IEnumerable<T> {

       private List<T> collection = new List<T>();

 

       public IEnumerator<T> GetEnumerator() {

              foreach (T each in collection) {

                     yield return each;

              }

       }

 

       IEnumerator IEnumerable.GetEnumerator() {

              return GetEnumerator();

       }

      

       public void ForEach(Action<T> action) {

              collection.ForEach(action);

       }

      

       public void link(T entity) {

              collection.Add(entity);

       }

}

 

that's ok, all of it.

7月27日

一不小心

BlockDataSource = new BlockDateOrderFilter(

       new BlockDataSource(

              new SpecifyDateRangeEntryVODataSourceFilter(

                   new SpecifyUserEntryVODataSourceFilter(

                      new EntryVODataSource(SpringContext.getManagerFactory().getEntryManager()),

                      SpecifyUser

                   ),

                   new LastWeek()

              )

       ),

       true

);

7月25日

generate Code Snippet @ vs2005

说实话看到xml就有些晕,不过相对于不断的重复
static readonly ILog logger = LogManager.GetLogger(typeof(DataSourceConcurrencyTest));
总是相对好些。
 
vs2005采用了snippet生成策略,使用xml来制定规则
直接看一下for和prop你就很容易写出上面的logger生成snippet,如下
 

<?xml version="1.0" encoding="utf-8" ?>

<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

       <CodeSnippet Format="1.0.0">

              <Header>

                     <Title>logger</Title>

                     <Shortcut>logger</Shortcut>

                     <Description>Code snippet for 'log4net' declaration</Description>

                     <Author>Survivalsoft Corporation</Author>

                     <SnippetTypes>

                            <SnippetType>Expansion</SnippetType>

                            <SnippetType>SurroundsWith</SnippetType>

                     </SnippetTypes>

              </Header>

              <Snippet>

                     <Declarations>

                            <Literal>

                                   <ID>ClassName</ID>

                                   <Default>ClassName</Default>

                                   <ToolTip>ClassName</ToolTip>

                            </Literal>

                     </Declarations>

                     <Code Language="csharp"><![CDATA[static readonly ILog logger = LogManager.GetLogger(typeof($ClassName$));]]>

                     </Code>

              </Snippet>

       </CodeSnippet>

</CodeSnippets>

 
重点就落在最后的<Decarations>和<Code>上,没什么难度,只是xml让我心里堵得慌。
 
不妨打开VIM,然后在cmd中输入,
 

:map <F5> 0idef <Esc>oend<Esc>O<Space><Space>

 

很轻很自由,我想这才是我想要的,呵呵

 

== update another snippet

<Snippet>

       <Declarations>

              <Literal>

                     <ID>name</ID>

                     <ToolTip>Class name</ToolTip>

                     <Default>SomeTest</Default>

              </Literal>

       </Declarations>

       <Code Language="csharp"><![CDATA[[TestFixture]

public class $name$ {

       [SetUp]

       public void setUp() {

              $selected$$end$

       }

 

       [TearDown]

       public void tearDown() { }

 

       [Test]

       public void test() {

      

       }

}]]>

       </Code>

</Snippet>

 

7月24日

Memory Load

测试一下页面数据源的内存情况
[Unit: Byte]
 

 

日志


1月29日

Hope it helps -_-!

发现21世纪还是需要跟不同的人不停的解释UTF8,而却一再遭到很奇怪的眼神。

 

string s = "hello world,日后再说!";

 

byte[] asciiBytes = Encoding.ASCII.GetBytes(s);

Console.WriteLine(ByteHelper.ToString(asciiBytes));

// 68 65 6c 6c 6f 20 77 6f 72 6c 64 2c 3f 3f 3f 3f 21

 

byte[] unicodeBytes = Encoding.Unicode.GetBytes(s);

Console.WriteLine(ByteHelper.ToString(unicodeBytes));

// 68 00 65 00 6c 00 6c 00 6f 00 20 00 77 00 6f 00 72 00 6c 00 64 00 2c 00 e5 65 0e 54 8d 51 f4 8b 21 00

 

byte[] utf8Bytes = Encoding.UTF8.GetBytes(s);

Console.WriteLine(ByteHelper.ToString(utf8Bytes));

// 68 65 6c 6c 6f 20 77 6f 72 6c 64 2c e6 97 a5 e5 90 8e e5 86 8d e8 af b4 21

 

注意:3f就是'?'

很多时候看到老外的软件也经常处理不好中文,就是因为ASCII编码以至于出现'?',尤其在编辑器和网络中(字符串和byte转换过程)丢失了数据

1月28日

Ftp Uploader Domain Design

设计需求:

1.将文件上传至Ftp

2.异步

3.被动进度查询

4.完成通知

5.异常

 

对象及职责:

FtpSite             肉鸡,保存ftp信息

FileUploader        管理并调度上传任务 [Singleton]

FileUploadTask      负责将文件上传至Ftp并提供相应信息

 

========================= Test Driven Code =============================================

FileUploader.Instance.StartUp();

 

FtpSite site = new FtpSite { FriendlyName = "Test Repo", Uri = "ftp://localhost", UserName = "gbvision", Pwd = "gbvision" };

 

FileUploadTask task1 = new FileUploadTask

{

    SourceFile = @"C:\Users\nonocast\Desktop\FTP\test1.rmvb",

    Destination = site,

    NameStrategy = NameStrategy.GUID,

    Completed = t => Console.WriteLine("{0} is Completed!", t.SourceFile)

};

 

FileUploadTask task2 = new FileUploadTask

{

    SourceFile = @"C:\Users\nonocast\Desktop\FTP\test2.rmvb",

    Destination = site,

    NameStrategy = NameStrategy.GUID,

    Completed = t => Console.WriteLine("{0} is Completed!", t.SourceFile)

};

 

FileUploader.Instance.Request(task1);

FileUploader.Instance.Request(task2);

 

while (FileUploader.Instance.ActiveTasks.Count > 0) {

    FileUploader.Instance.ActiveTasks.ForEach(

        task => Console.WriteLine("{0}%\t{1}/{2}", task.Progress, task.CommitBytes, task.FileSize)

    );

    Console.WriteLine("---------------------------");

 

    Thread.Sleep(1000);

}

 

FileUploader.Instance.ShutDown(); 

1月23日

One of my strange dream is ...

在CodeProject上看到一篇文章,顺大便看了最下面的About Him
 

Microsoft Certified Solution Developer (.NET) working with a software development company in India.

Achieved Masters in Computer Applications and Bachelor degree in Electronics

Areas of interest: AI..specifically Genetic Algorithms, Machine learning, automation engineering, user interface designs, human computer interaction, biotechnology, nanotechnology, networking technologies (computers as well as social)


One of my strange dreams that I want to come true in my lifetime: Interacting with the computer without opening the eye and without lifting a finger (and ofcourse without having holes in your bodies like the Matrix)
0 5000 10000 20000 50000
WorkingSet 16273408 32722944 42766336 64860160 130338816
VirtualBytes 119070720 119070720 136437760 155443200 224911360

 

这里的0, 5000 ... 50000是条目数量

测试条目包含500字(U+)的数据

这样的话,基本来说在10000条占用主存26.5M [42.7M-16.2M]

换句话来说,这个数量级上的DataSource可以做到FullInMemory,而无需考虑Virtual Proxy

 

量化可以使得在不同的level上做出不同的策略,而无需考虑一种AllInOne的BT方法。

这样可以更潇洒,更自如,更因地制宜

 

PS,第一次用Excel画表,很兴奋,也不知道兴奋什么,呵呵

迟到的度量工作

 
很简单的代码,

public class PerformanceEntry {

       public static void Main(string[] args) {

              StringBuilder sb = new StringBuilder();

              for (int i = 0; i < 50; i++) {

                     sb.Append("零一二三四五六七八九");

              }

              string content = sb.ToString();

 

              List<string> strs = new List<string>();

             

              Console.WriteLine("ready?");

              Console.ReadLine();

 

              for (int i = 0; i < 10000; i++) {

                     strs.Add(string.Format("{0}-{1}", content, i));

              }

 

              Console.ReadLine();

       }

}

 

but,分配这10000个字符串用了多少内存,你清楚吗?

ok,我们可以使用Task Manager和Perfmon,他们都是随Windows一起提供的

 

Task Manager我就不多说了,看图

 

分配后的情形,

 

 

和进程内存使用情况关系最密切的计数器包括:

 

Mem Usage (内存使用):在线帮助将其称为进程的工作集(尽管很多人称之为驻留集)——当前在主存中的页面集。但是这个数值包含能够和其他进程共享的页面,因此要注意避免重复计算。比方说,如果要计算共享同一个 DLL 的两个进程的总内存占用情况,不能简单地把“内存使用”值相加。

Peak Mem Usage (内存使用高峰值):进程启动以来 Mem Usage(内存使用)字段的最大值。

Page Faults (页面错误):进程启动以来要访问的页面不在主存中的总次数。

VM Size (虚拟内存大小):联机帮助将其称为“分配给进程私有虚拟内存总数。”更确切地说,这是进程所 提交的内存。如果进程保留内存而没有提交,那么该值就与总地址空间的大小有很大的差别。  

  

然后是PerfMon,这个就更加直观,更加专业,使起来也倍顺手

run -> perfmon 来启动PerfMon

删除下方所有的Counter,然后右键添加

 

 

这里的表达方式有些另类,of course,也可以说是更加professional,对应关系如下,

计数器名

类别

说明

as TaskManager

Working Set

Process

驻留集,当前在实际内存中有多少页面

Mem Usage

Private Bytes

Process

分配的私有虚拟内存总数,即提交的内存

VM Size

Virtual Bytes

Process

虚拟地址空间的总体大小,包括共享页面。因为包含保留的内存,可能比前两个值大很多

 -

Page Faults / sec(每秒钟内的页面错误数)

Process

每秒中出现的平均页面错误数

链接到 Page Faults(页面错误),显示页面错误总数

Committed Bytes(提交的字节数)

Memory

提交状态的虚拟内存总字节数

 -

 

 然后你就可以得到如下的内存变化,

 

 

最后我们可以根据变化前后的Working Set值来计算增量

40.2M - 15.9M / 10000 = 2.4K

也就是说一个长度为500的string占了2.4K,就算是Unicode,不也应该是1000字节嘛,faint!

 

你可以将配置save起来,存放到svn中,以使整个team可以share这个配置,PERFECT!

7月20日

夺月

TestDriven.NET
 
NCover & its explorer
 
CruiseControl.NET
 
NANT
 
log4net
 
of course use Ruby to mix them
7月3日

Caller on .NET

Caller on .NET

 

easy,

public class CallerTest {

       static public void Main(string[] args) {

              try {

                     level1();

              } catch (Exception ex) {

       Console.WriteLine(ex);

              } finally {

                     Console.ReadLine();

              }

       }

 

       static void level1() {

              level2();

       }

 

       static void level2() {

              StackTrace st = new StackTrace();

              if (st.FrameCount > 1) {

                     StackFrame stFrame = st.GetFrame(1);

                     Console.WriteLine(stFrame.GetMethod());

              }

       }

}

 

如果打开fNeedFileInfo开关,new StackTrace(true), 则可以trace到相应的文件名以及行号。

 

然后我们从对象的角度来观察,

public class CallerTest {

       class Callee {

              public void callAtCallee() {

                     StackTrace st = new StackTrace(1, true);

                     Console.WriteLine("{0}.{1}", st.GetFrame(0).GetMethod().ReflectedType.Name, st.GetFrame(0).GetMethod().Name);

              }

       }

 

       class Caller {

              public void callAtCaller(Callee ee) {

                     ee.callAtCallee();

              }

       }

 

       static public void Main(string[] args) {

              try {

                     new Caller().callAtCaller(new Callee());

              } catch (Exception ex) {

       Console.WriteLine(ex);

} finally {

                     Console.ReadLine();

              }

       }

}

 

其中st.GetFrame(0).GetMethod().ReflectedType.Name是指相应MethodBase所在的Class,st.GetFrame(0).GetMethod().Name则是方法名称。

这样我们就可以很容易在callAtCallee的方法中的得到调用Class以及方法signature.

 

至于要得到具体哪个对象调用则好像有些难度...

知道的话给我留个方法吧,谢谢了J

6月20日

中文首字拼音

1 /// <summary>

2 /// 获取一串汉字的拼音声母

3 /// </summary>

4 /// <param name="chinese">Unicode格式的汉字字符串</param>

5 /// <returns>拼音声母字符串</returns>

6 public static String Convert(String chinese) {

7 char[] buffer = new char[chinese.Length];

8 for (int i = 0; i < chinese.Length; i++) {

9 buffer[i] = Convert(chinese[i]);

10 }

11 return new String(buffer);

12 }

13

14 /// <summary>

15 /// 获取一个汉字的拼音声母

16 /// </summary>

17 /// <param name="chinese">Unicode格式的一个汉字</param>

18 /// <returns>汉字的声母</returns>

19 public static char Convert(Char chinese) {

20 Encoding gb2312 = Encoding.GetEncoding("GB2312");

21 Encoding unicode = Encoding.Unicode;

22

23 // Convert the string into a byte[].

24 byte[] unicodeBytes = unicode.GetBytes(new Char[] { chinese }); 25 // Perform the conversion from one encoding to the other.

26 byte[] asciiBytes = Encoding.Convert(unicode, gb2312, unicodeBytes);

27

28 // 计算该汉字的GB-2312编码

29 int n = (int)asciiBytes[0] << 8;

30 n += (int)asciiBytes[1];

31

32 // 根据汉字区域码获取拼音声母

33 if (In(0xB0A1, 0xB0C4, n)) return 'a';

34 if (In(0XB0C5, 0XB2C0, n)) return 'b';

35 if (In(0xB2C1, 0xB4ED, n)) return 'c';

36 if (In(0xB4EE, 0xB6E9, n)) return 'd';

37 if (In(0xB6EA, 0xB7A1, n)) return 'e';

38 if (In(0xB7A2, 0xB8c0, n)) return 'f';

39 if (In(0xB8C1, 0xB9FD, n)) return 'g';

40 if (In(0xB9FE, 0xBBF6, n)) return 'h';

41 if (In(0xBBF7, 0xBFA5, n)) return 'j';

42 if (In(0xBFA6, 0xC0AB, n)) return 'k';

43 if (In(0xC0AC, 0xC2E7, n)) return 'l';

44 if (In(0xC2E8, 0xC4C2, n)) return 'm';

45 if (In(0xC4C3, 0xC5B5, n)) return 'n';

46 if (In(0xC5B6, 0xC5BD, n)) return 'o';

47 if (In(0xC5BE, 0xC6D9, n)) return 'p';

48 if (In(0xC6DA, 0xC8BA, n)) return 'q';

49 if (In(0xC8BB, 0xC8F5, n)) return 'r';

50 if (In(0xC8F6, 0xCBF0, n)) return 's';

51 if (In(0xCBFA, 0xCDD9, n)) return 't';

52 if (In(0xCDDA, 0xCEF3, n)) return 'w';

53 if (In(0xCEF4, 0xD188, n)) return 'x';

54 if (In(0xD1B9, 0xD4D0, n)) return 'y';

55 if (In(0xD4D1, 0xD7F9, n)) return 'z';

56 return '\0';

57 }

58

59 private static bool In(int Lp, int Hp, int Value) {

60 return ((Value <= Hp) && (Value >= Lp));

61 }

62

 

Usage:

Convert("中国")     =>     z

6月10日

一点点关于window command line

test.rb
----------------------------------------------------------------------
require 'pp'
pp ARGV.length
pp ARGV
 
test.cmd
----------------------------------------------------------------------
@ruby "F:\nowProject\smooth\script\test.rb" %*
 
 
然后在nonocast/sendto中加入test.cmd的快捷方式
通过测试发现
如果我选中20个文件然后发送到test.cmd,这20个文件就会以20个字符串传到我的rb里面
过去因为老是看到
xxx.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
一直以为最多只带9个参数,呵呵
 
原来可以蛮多的
其实是很简单的问题,但可以做出一些比较有用的功能,呵呵
 
在参数和重定向间,我原来一直更倾向于重定向,因为这样的耦合可以更低
但今天就发现重定向固然有他的好处,但限制也是同样多的
比如不能得到源的一些信息,文件类型啦,格式啊
这里的话参数就更加有优势
再次从一个方面证明了没有最好的,只有适合的
 
大家手牵手,生活很美好!
5月19日

连接

1. flash <- js -> dotnet
 
flash.(v8)
----------------------------------------------
使用ExternalInterface来和js沟通
非常容易:)
首先需要
import flash.external.*;
 
flash -> js
ExternalInterface.call("methodNameInJs", param1, param2);
没有参数就直接
ExternalInterface.call("methodNameInJs");
就ok了
 
flash <- js
ExternalInterface.addCallback("methodAliasNameInAs", null, methodNameInAs);
function methodNameInAs(param1, param2, param3) { }
这里需要注意的是AS和JS都是区分大小写的
 
 
js
------------------------------------------------
js -> flash
首先得到flash对象

function thisMovie(movieName) {
    if (navigator.appName.indexOf("Microsoft") != -1) {
        return window[movieName]
    } else {
        return document[movieName]
    }
}
 
然后调用flash中导出的method就ok了

thisMovie("flashName").methodAliasNameInAs(param1, param2, param3);
 
 
js <- flash
function methodNameJs(param1, param2) { }
 
js <-> dotnet ...
 

2. plain text -> ruby -> http post -> dotnet
 
client.
--------------------------------------------------
require 'net/http'
require 'uri'
 
data = ""
File.open('data.txt') do |f|
 data = f.readlines
 data.join
end
 
res = Net::HTTP.post_form(URI.parse('http://rssvr:88/Default.aspx'), {'data'=>data})
 
puts res.body

server.
---------------------------------------------------
protected void Page_Load(object sender, EventArgs e) {
 logger.Info(Request.form['data']);
}
 
记得在aspx中Page后面加入ValidateRequest="flase"
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="HttpAnalyse.site._Default"  ValidateRequest="false"%>
 
还有就是编码问题,在Web.config中<system.web>节点中加入
<globalization requestEncoding="GB2312" responseEncoding="GB2312" uiCulture="zh-CN" culture="zh-CN" fileEncoding="GB2312" />
 
4月29日

管道的力量

如果进程是轻量的,如果IPC是优雅的,那么很自然就会使用多种语言协同作业
但如果进程是重量的,IPC是扭曲的,那么很自然的就会使得线程看上去是那么的自然,是必然的
那么语言间的协同也就不复存在,如果没有协同那么必定要造无数个重复的轮子,早就无数个大的可怜的project
这就是宿命,在Windows中的悲哀
 
如果你用C#写一个程序明明一些内容是适合srcipt解决的,但你就是找不到在合适的成本下让他们合作的方式。有把合作的能力早就能用C#完成这些工作了,而且还规避了由pipe或是socket之间产生的不可预料的异常以及不可想象的开销。
 
进程 管道 重定向 在 SHELL 中跑的是如此欢快
当然也不可避免带来了依赖的复杂度,呵呵
 
3月31日

xmlSerialize abc

在做对象序列化的时候遭遇了一下xml serializer,在dotnet下是非常省心的。

User nonocast = new User("nonocast");
User syy 
= new User("shenyuyang");
User beatmania 
= new User("beatmania");
User tony 
= new User("tonykong");

List
<User> users = new List<User>();
users.Add(nonocast.setId
<User>(1));
users.Add(syy.setId
<User>(2));
users.Add(beatmania.setId
<User>(3));
users.Add(tony.setId
<User>(4));

XmlSerializer serializer 
= new XmlSerializer(typeof(List<User>));
serializer.Serialize(
new FileStream(@"users.xml", FileMode.Create), users);


这样就可以将对象序列化到users.xml中去了
<?xml version="1.0"?>
<ArrayOfUser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  
<User id="1">
    
<Name>nonocast</Name>
  
</User>
  
<User id="2">
    
<Name>shenyuyang</Name>
  
</User>
  
<User id="3">
    
<Name>beatmania</Name>
  
</User>
  
<User id="4">
    
<Name>tonykong</Name>
  
</User>
</ArrayOfUser>


这里之所以name是子节点,而id作为属性是因为在id申明的地方加了一句Attribute< br>
[XmlAttribute("id")]
public int Id { getset; }


如果需要将对象序列化到string中只需更换相应的strategy就ok了,形如:

StringBuilder sb = new StringBuilder();
serializer.Serialize(
new StringWriter(sb), users);


反序列化同样也是两句:

XmlSerializer serializer = new XmlSerializer(typeof(List<User>));
List
<User> users = (List<User>)serializer.Deserialize(new FileStream(@"users.xml", FileMode.Open));


这样就轻松地完成了xml序列化和反序列化,比c++要爽太多,比yaml还略逊色一些。
比上不足,比下大有余吧:)

3月29日

ss abc

 如果只是用鼠标简单的点点vs和vss来做版本管理,可以说需要做大量的重复工作来管理同步dll,以及各个solution之间的依赖关系,尤其是在不同的vss仓库下做一些同步工作。

首先需要升级一下command line下的vss工具ss
上来先看看三个环境变量:
SSUSER
SSPWD
SSDIR

ss会根据上面这三个变量来选择相应的vss仓库并登录

一般来说:
set SSUSER=nonocast
set SSPWD=123456
set SSDIR=//rssvr/vss/survivalsoft
ss Create $test.project

即可以在survivalsoft这个vss仓库中添加一个test.project的project,很easy吧..

一般来说用户名和密码都是相对固定的,可以直接写到环境变量中去
这里可以通过set SSDIR非常容易的切换vss仓库

这个抛砖引玉介绍几条command,具体的可以参考VSS Documentation

1.CP
sets the current project path.
Syntax: ss CP <project> [-H] [-I-] [-Y] [-?]

通过SSDIR切换仓库,然后通过CP切换project,基本完成project定位

然后就是
2.GET
Retrieves read-only copies of the specified Visual SourceSafe files or projects to your working folder.
Syntax: ss Get <items> [-G] [-H] [-I-] [-N] [-O] [-R] [-V] [-W] [-Y] [-?]

这里的Get和check out的区别就在于read-only
Get的权限级别要比check out低很多

在定位project以后,
ss Get * -R
就可以把所有的files全部抓下来

这里的-R是:
Used recursively on a project (-R option), this command retrieves all the files in the project and its subprojects, and places them in subfolders of the same name in your working folder.

抓下来的路径就是当前你所在的路径 :)


当然和Get相对应的就是
3.Add
Adds new files to the Visual SourceSafe database.
Syntax:
ss Add <local files> [-B] [-C] [-D-] [-H] [-I-] [-K] [-N] [-O] [-R] [-W] [-Y] [-?]
example:
    Adds all files in the current folder to the current project:
    ss Add *
    Adds all files in the current folder and all subfolders to the current project:
    ss Add *.* -R


最后再给出一些有用的Command Options,其实vss doc上都全,这里给自己一个方便
1.-C
Specifies a comment for a command. If you do not specify the -C option, Visual SourceSafe requests a comment for each item specified on the command line. If you do specify the option, all items receive the same comment.
比如说你在create project的时候
ss Create xxxxx
然后他会提示你输入Comment for it:
如果这里用
ss Create xxxxx -C-
他就不放这个P了,所以在bat中还是很实用的一个参数,很多命令都需要配合他来用。

在Add的时候添加新的item,也同样需要-C-去掉输入Comment的提示

2.-I
Indicates what factors Visual SourceSafe should ignore when comparing two files. The following table lists ways to use the -I option.

一般来说在做dll的时候不需要比较版本,直接覆盖上去就结了
所以在Add的时候配合-I-一起使用

3.-Y
Specifies a user name or user name and password. Use this option if you want to execute a command as another user.

-Y<user name>
Specifies a user name.

-Y<user name>,<password>
Specifies a user name and password.


4.-G
这个option就比较牛X了
Sets options for a retrieved working copy. Many of the switches for this option provide command-specific overrides that can be set in the Ss.ini file.

-GL<path>
Copies a file to the specified folder, not to the current or working folder.
Get到指定任意目录。
eg: ss -GLc: Get *
注意这里的路进不能带有空格


小结一下,
如果我要把\\rssvr\vss\survivalsoft中的assembly目录中的所有内容抓到C:\Documents and Settings\nonocast\桌面\lib这个路径中去,命令如下:
cd C:\Documents and Settings\nonocast\桌面\lib
set ssuser=nonocast
set sspwd=123456
set ssdir=//rssvr/vss/survivalsoft
ss CP assembly
ss Get * -R

uups..:) EASY, just abc

如果你觉得bat不爽,也可以用其他script来代替
pull.rb
--------------------------------------------------------------------------------------
# must not delete any user's item, just add new or overwrite it

require 'ftools'

$ssdir='//rssvr/vss/survivalsoft'

def sh cmd
  Kernel::system(cmd)
end

def update(target)
  targetDir = File.dirname(__FILE__) + "/#{target}"
  if !File.directory?(targetDir)
    File.mkpath(targetDir)
  end

  ENV['SSDIR']=$ssdir
  sh "ss Get $/#{target}/*.dll -GL./#{target}"
end

if __FILE__ == $0
  update("vendor")
  update("assembly")
end
-------------------------------------------------------------------------------------
BTW:在环境变量中预先设置了相应的ssuser&sspwd

reference
web:
http://martinfowler.com/articles/ciWithCom.html

local:
vss documention
H:\develop data\General\vss\命令行中使用VSS.txt
H:\develop data\专栏\配置\ABSManageSystem.bat

hah

The Visual SourceSafe command line utility SS supports most commands available through Visual SourceSafe Explorer, and some that are only available on the command line. The command line is often used by programmers who find typing commands faster than launching Visual SourceSafe Explorer and using menus. Details of the SS utility are provided in SS Utility.

 

程序员应该勇于直面惨淡的shell,用shell来完成更多的工作,don't be duplicate.

每次的重复让我觉得恶心

 
 

组合拳 <= vim+ shell + tool + script

 
 
 
 其实利用好tool之间的合作,加上网络可以做出很旋的功能,解决很多很实际的问题
尤其是利用vim+ruby搞一些小的shell script出来
这样不仅轻巧,跨平台,关键是很惬意
 
在这方面自己还是相当欠缺的
要有一个熟悉的shell,windows下只能凑合用用command,当然考虑升级一下cygwin,但多少还是有些思想上的别扭
shell的关键点在于柔和,协调工作,利用重定向来配合输入输出
 
再次就是需要熟练掌握vim和ruby语法,尤其是vim的博大精深,加之ruby的灵巧简洁
 
从扩展来说要熟悉各种周遭的shell工具,熟悉的越多,组合的效能越大
 
在.net下做项目,免不了多个项目的管理切换
vim+ruby + cmd + ss/csc/msdev
差不多就可以代劳很多体力活了
 
web:
http://martinfowler.com/articles/ciWithCom.html
 
local:
H:\develop data\专栏\配置\ABSManageSystem.bat
H:\develop data\专栏\配置\Building a Project from the Command Line.txt
 
vss help:
Visual SourceSafe Reference - Command Line Reference
 
3月25日

singleton abc

偶然间看到继承的 Singleton模式的实现
想法挺好的,只是觉得为了一个singleton不是太值得,更多是再玩,其实用 Generics用很少的代码就可以走掉的
BTW:这里不考虑multithread,其实 singleton本身属于设计层面,无需涉及线程之类的细节。


class SingletonT<T> where T: new(){
    
static protected T instance = new T();
    
static public T getInstance() {
        
return instance;
    }
}

class SomeClass : SingletonT<SomeClass> {
    
public void fire() {
        Console.WriteLine(
"hello singleton!");
    }
}

class EntryPoint {
    
public static void Main(string[] args) {
        SomeClass.getInstance().fire();
    }
}

这里根据个人喜好可以将getInstance()变为Instance { get{..} }

最后当然要感谢diclogic,呵呵
3月23日

event abc

习惯在了在C++中肆意PostThreadMessage,到了.net下有些乱了方寸。还好有event,不过千万不要和c#中的那个event搞在一起

    // 线程间传送消息
    class Program {
        
static AutoResetEvent autoEvent = new AutoResetEvent(false);
        
static Queue<string> messageQueue = new Queue<string>();

        
static void Main(string[] args) {
            
new Thread(new ThreadStart(messageLoop)).Start();
            
new Thread(new ThreadStart(threadProc)).Start();
        }

        
static void messageLoop() {
            Queue
<string> transferQueue = new Queue<string>();
        
            
while (autoEvent.WaitOne()) {            
                
// 尽可能的减少messageQueue被锁住的时间
                foreach(string msg in messageQueue) {
                    transferQueue.Enqueue(msg);
                }
                messageQueue.Clear();

                
foreach (string msg in transferQueue) {
                    Console.WriteLine(msg);
                }
                transferQueue.Clear();
            } 
// while
        }

        
static void threadProc() {
            
// 可以想象这里是网络的接收线程,客户端在源源不断的向这里发送数据

            
lock (messageQueue) { messageQueue.Enqueue("Hello Wolrd!"); }
            autoEvent.Set();

            
lock (messageQueue) { messageQueue.Enqueue("today is a good day"); }
            autoEvent.Set();

            
lock (messageQueue) { messageQueue.Enqueue("let it be"); }
            autoEvent.Set();
        }
    }

这里的event相当于是一个dirty flag,只要messageQueue加入了message就使这个event激活了,脏一次也是脏,脏两次也是脏
呵呵

这里再简单补充一下event的基本概念,主要参考Win32多线程程序设计

event有两种状态分别是:
激发和未激发
其实就是0,1

有两种使用模式:
手动和自动

手动是指再激发后不会自动重置,必须靠程序操作(调用ResetEvent())才能将其从激发状态设为非激发状态
而自动则表示这个event将在变成激发状态(因而唤醒一个线程)之后,自动重置(reset)为非激发状态

SetEvent: 设为激发状态,Set N次也是激发状态
ResetEvent: 设为非激发状态


从上面的代码可以看到xxxevent.WaitOne就会将event从激发态变为非激发态。