public class SingletonDemo
{
private static SingletonDemo theSingleton = null;
private SingletonDemo() { }
public static SingletonDemo Instance()
{
if (theSingleton == null)
{
theSingleton = new SingletonDemo();
}
return theSingleton;
}
static void Main(string[] args)
{
SingletonDemo s1 = SingletonDemo.Instance();
SingletonDemo s2 = SingletonDemo.Instance();
if (s1.Equals(s2))
{
Console.WriteLine("see, only one instance!");
}
}
}
分类目录归档:后端
.net mvc 中使用ActionFilterAttribute过滤器
过滤器是mvc中常用的
在.net mvc 中直接继承和实现ActionFilterAttribute类就可以了
很简单
下面贴出一个例子
过滤器:
public class UseStopwatchAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
filterContext.Controller.ViewData["stopWatch"] = stopWatch;
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Stopwatch stopWatch = (Stopwatch)filterContext.Controller.ViewData["stopWatch"];
stopWatch.Stop();
Random r = new Random();
filterContext.Controller.ViewData["elapsedTime"] = stopWatch.ElapsedMilliseconds
+ " milliseconds - Rand " + r.Next(1000).ToString();
}
}
这的话这个过滤器就写好了
在使用的时候只要在controller上写上就行了
[UseStopwatch]
public class ProductsController : Controller
{
//
// GET: /Store/Products/
public ActionResult List()
{
return View();
}
public ActionResult Details()
{
return View();
}
public ActionResult AddReview()
{
return View();
}
}
C#中同步、异步读取进程输出信息
1、异步的:
p.StartInfo.RedirectStandardError = true;
p.ErrorDataReceived += new DataReceivedEventHandler(OutputInfo);
p.Start();
p.BeginErrorReadLine();
private void OutputInfo(object sendProcess, DataReceivedEventArgs output){
if (!String.IsNullOrEmpty(output.Data))
{
//处理方法...
}
}
2、同步的
p.StartInfo.RedirectStandardError = true;
p.Start();
StreamReader sr = ffmpeg.StandardError;
p.WaitForExit();//之后就可以从sr里读了
C#中枚举类型enum的使用
1、关于enum的定义
enum Fabric
{
Cotton = 1,
Silk = 2,
Wool = 4,
Rayon = 8,
Other = 128
}
2、符号名和常数值的互相转换
Fabric fab = Fabric.Cotton;
int fabNum = (int)fab;//转换为常数值。必须使用强制转换。
Fabric fabString = (Fabric)1;//常数值转换成符号名。如果使用ToString(),则是((Fabric)1).ToString(),注意必须有括号。
string fabType = fab.ToString();//显示符号名
string fabVal = fab.ToString ("D");//显示常数值
3、获得所有符号名的方法(具体参见Enum类)
public enum MyFamily
{
YANGZHIPING = 1,
GUANGUIQIN = 2,
YANGHAORAN = 4,
LIWEI = 8,
GUANGUIZHI = 16,
LISIWEN = 32,
LISIHUA = 64,
}
foreach (string s in Enum.GetNames(typeof(MyFamily)))
{
Console.WriteLine(s);
}
4、将枚举作为位标志来处理
根据下面的两个例子,粗略地说,一方面,设置标志[Flags]或者[FlagsAttribute],则表明要将符号名列举出来;另一方面,可以通过强制转换,将数字转换为符号名。说不准确。看下面的例子体会吧。注意:
- 例一:
Fabric fab = Fabric.Cotton | Fabric.Rayon | Fabric.Silk;
Console.WriteLine("MyFabric = {0}", fab);//输出:Fabric.Cotton | Fabric.Rayon | Fabric.Silk;
- 例二:
class FlagsAttributeDemo
{
// Define an Enum without FlagsAttribute.
enum SingleHue : short
{
Black = 0,
Red = 1,
Green = 2,
Blue = 4
};
// Define an Enum with FlagsAttribute.
[FlagsAttribute]
enum MultiHue : short
{
Black = 0,
Red = 1,
Green = 2,
Blue = 4
};
static void Main( )
{
Console.WriteLine(
"This example of the FlagsAttribute attribute n" +
"generates the following output." );
Console.WriteLine(
"nAll possible combinations of values of an n" +
"Enum without FlagsAttribute:n" );
// Display all possible combinations of values.
for( int val = 0; val <= 8; val++ )
Console.WriteLine( "{0,3} – {1}", val, ( (SingleHue)val ).ToString( ) );
Console.WriteLine( "nAll possible combinations of values of an n" + "Enum with FlagsAttribute:n" );
// Display all possible combinations of values.
// Also display an invalid value.
for( int val = 0; val <= 8; val++ )
Console.WriteLine ( "{0,3} – {1}", val, ( (MultiHue)val ).ToString( ) );
}
}
/*
This example of the FlagsAttribute attribute
generates the following output.
All possible combinations of values of an
Enum without FlagsAttribute:
0 – Black
1 – Red
2 – Green
3 – 3
4 – Blue
5 – 5
6 – 6
7 – 7
8 – 8
All possible combinations of values of an
Enum with FlagsAttribute:
0 – Black
1 – Red
2 – Green
3 – Red, Green
4 – Blue
5 – Red, Blue
6 – Green, Blue
7 – Red, Green, Blue
8 – 8
*/
5、枚举作为函数参数。经常和switch结合起来使用。下面举例
public static double GetPrice(Fabric fab)
{
switch (fab)
{
case Fabric.Cotton:
return (3.55);
case Fabric.Silk:
return (5.65);
case Fabric.Wool:
return (4.05);
case Fabric.Rayon:
return (3.20);
case Fabric.Other:
return (2.50);
default:
return (0.0);
}
}
6、上面三点一个完整的例子
//enum的定义
public enum Fabric : short
{
Cotton = 1,
Silk = 2,
Wool = 3,
Rayon = 8,
Other = 128
}
//将枚举作为参数传递
public static double GetPrice(Fabric fab)
{
switch (fab)
{
case Fabric.Cotton: return (3.55);
case Fabric.Silk : return (5.65);
case Fabric.Wool: return (4.05);
case Fabric.Rayon: return (3.20);
case Fabric.Other: return (2.50);
default: return (0.0);
}
}
public static void Main()
{
Fabric fab = Fabric.Cotton;
int fabNum = (int)fab;
string fabType = fab.ToString();
string fabVal = fab.ToString ("D");
double cost = GetPrice(fab);
Console.WriteLine("fabNum = {0}nfabType = {1}nfabVal = {2}n", fabNum, fabType, fabVal);
Console.WriteLine("cost = {0}", cost);
}
7、Enum类的使用
Enum.IsDefinde、Enum.Parse两种方法经常一起使用,来确定一个值或符号是否是一个枚举的成员,然后创建一个实例。Enum.GetName打印出一个成员的值;Enum.GetNames打印出所有成员的值。其中注意**“`typeof“`**的使用。这一点很重要。
public enum MyFamily
{
YANGZHIPING = 1,
GUANGUIQIN = 2,
YANGHAORAN = 4,
LIWEI = 8,
GUANGUIZHI = 16,
LISIWEN = 32,
LISIHUA = 64,
}
string s = "YANGHAORAN";
if (Enum.IsDefined(typeof(MyFamily), s))
{
MyFamily f = (MyFamily)Enum.Parse(typeof(MyFamily), s);
GetMyFamily(f);
Console.WriteLine("The name is:" + Enum. GetName(typeof(MyFamily), 2));
string[] sa = Enum.GetNames(typeof(MyFamily));
foreach (string ss in sa)
{
Console.WriteLine(ss);
}
}
list contains 类
Subscription sub = new Subscription();
sub.Appname = subName;
if (this.Subscriptions.Contains(sub,new SubcriptionComparer<Subscription>()))
return true;
else
return false;
class SubcriptionComparer<T> : IEqualityComparer<T>
where T : Subscription
{
public int GetHashCode(T obj)
{
return obj.GetHashCode();
}
public bool Equals(T t1, T t2)
{
return t1.Appname == t2.Appname;
}
}
Rhino.Mocks.Exceptions.ExpectationViolationException : Expected #0, Actual #1.
failed: Rhino.Mocks.Exceptions.ExpectationViolationException : IBandwidthDataService.GetDataForCustom(100, 2010/1/11 14:35:31, 2010/2/11 14:35:31, 1.00:00:00); Expected #0, Actual #1.
模拟的方法加上.IgnoreArguments()
Java连接各种数据库
1. Oracle8/8i/9i数据库(thin模式)
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);
2. DB2数据库
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
3. SQL Server7.0/2000数据库
String className = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
String url = "jdbc:sqlserver://localhost:1433;DatabaseName=testdb";
String user="sa";
String password="sa";
Connection conn= DriverManager.getConnection(url,user,password);
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";//mydb为数据库
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
4. Sybase数据库
Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB为你的数据库名
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);
5. Informi数据库
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword"; //myDB为数据库名
Connection conn= DriverManager.getConnection(url);
6. MySQL数据库
Class.forName("org.gjt.mm.mysql.Driver").newInstance();//或者Class.forName("com.mysql.jdbc.Driver");
//myDB为数据库名
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
Connection conn= DriverManager.getConnection(url);
7. PostgreSQL数据库
Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库名
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);
8. access数据库直连用ODBC的
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
String url="jdbc:odbc:Driver={MicroSoft Access Driver
(*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
Connection conn = DriverManager.getConnection(url,"","");
Statement stmtNew=conn.createStatement() ;
Java内存机制(堆与栈)的分配
Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个 变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配 Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个 变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的 首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象 起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍 然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
JavaBean规范
作为Java程序员,对于 JavaBean也许你会说再熟悉不过了,它活跃于系统的很多层,不同的说法有 PO、VO、DTO、POJO。然而它无外乎就是一个Class类,带上些属性和它们的setter/getter方法,set/get后面那一个字母大 写。虽然我们现在很少把JavaBean与那个古老的2.0的EJB搞混,但为什么明明用IDE为属性生成的getter/setter方法,应用一运 行,还是报找不到某个bean属性的setter或getter方法呢?
要知道,在Sun的网站上那个关于JavaBean规范的PDF文档可是有足足实实的114页啊。难免有些规则有点古怪,至使知名的IDE都难以应对,所以我们还是有必要了解其中二三,来规范我们的JavaBean和解释一些情形。
Sun的关于JavaBean规范见:http://java.sun.com/javase/technologies/desktop/javabeans/docs/spec.html,其中可下载到 JavaBean规范的PDF文档。
实际中的问题
首先,当然还是要说它的属性及 setter/getter 方法。属性以小写字母开头,驼峰命名格式,相应的 getter/setter 方法是 get/set 接上首字母大写的属性名。多数情况是对的,且当前流行的 IDE(Eclipse、JBuilder) 也都认这个死理,这里 NetBean 值得表扬一下。但要是碰到些遗留的代码中属性名不规范,或者有些人就是顽固,或真是对属性命名犹豫不决时的写下的代码时,那还是有得你研究一下。
这里来看看 Eclipse 为几个属性生成的 getter/setter 方法吧:
- sName(从 C 转过来的,受匈牙利的影响,认为 Name 是个字符串,所以加个前缀 s)
- getSName()/setSName(String name)
- URL (平时认为是缩略语/专有名词,理当全部大写,这在我们对待 ID 时经常发生的)
- getURL()/setURL(String url)
上面第一个由 Eclipse 为我们生成的 getSName()/setSName(String name) 方法,参照 JavaBean 规范来说,其实是错误的。如果出现这样的方法,放到我们的标签(像 Struts 标签,如 <s:textfield name="sName"></s:textfield>), 或是进行 Hibernate/iBatis 那种映射时,你就能收到报 找不到 sName 属性相应的 getter/setter 方法 那样的错误。不是明明有 getSName() 和 setSName(String name),可是方法名错了,正确的版本应该是 getsName() 和 setsName(String name)。
前面首先解释了属性命名不规范产生问题的原因,现在就来更仔细的了解关于 JavaBean 属性及其 getter/setter 方法的约定,有些是硬性的。
属性与存取访问的规定
为 JavaBean 创建属性时,必须牢记:缩略语通常被视为一个独立的单词,而不是单个字母。例如,URL 对应的属性名应该用 url,相应的 getUrl()/setUrl(),所以 ID 还是用 id 作为属性吧,相应的 getId()/setId()。
规范中另一个特别的地方就是,第二个字母为大写的属性名要区别对待。如果属性名的第二个字母 是大写的,那么该属性名直接用作 getter/setter 方法中 get/set 的后部分,就是说大小写不变。这就是为什么 sName 对应的存取方法是 getsName()/setsName() 的原因,不能不说这条规则很令人费解。那就更有必要看看下面表格的规范:

属性是首字母大写,次字母小写是,你永远都找不到它的 getter/setter 方法的,对这个属性的使用是会害人的。对于 boolean 类型属性的 getter 方法是 isXxx() 还是 getXxx() 就自己决定了,isXxx() 应该更接近于自然语言,更顺溜些。
知道了属性及存取方法的规定,那么你即使是面对古老代码,在使用标签来引用或与 Hibernate/iBatis 等进行映射,你就知道该填什么样的属性名了。
还有一个我们很少碰触到的是关于可索引属性的 getter/setter 方法(这方面 C# 表现的比 Java 要优秀),比如有属性private OrderItem[] orderItem;
那它相应的 getter/setter 除常见的两个外,还有带索引参数的两个版本,如下:
public OrderItem[] getOrderItem();
public void setOrderItem(OrderItem[] newArray);
public OrderItem[] getOrderItem(int index);
public void setOrderItem(int index, OrderItem orderItem);
关于 Bean 导航
最后就是 Bean 导航的规范,通常用点记法(dot notation) 来引用属性,同时也要注意索引属性的访问。在 Web MVC 的表单中,以及标签中, Jarkata-Commons-BeanUtils 中用得很多。看点记法的示例:

比如像 Struts1 标签:
<html:text property="stocks[1].code"/>
会显示出 FormBean 中 stocks 列表的第二个元素的 code 属性,提交就填充到相应的位置上去。
PO VO DTO POJO
PO :persistent object持久对象
1 .有时也被称为Data对象,对应数据库中的entity,可以简单认为一个PO对应数据库中的一条记录。
2 .在hibernate持久化框架中与insert/delet操作密切相关。
3 .PO中不应该包含任何对数据库的操作。
POJO :plain ordinary java object 无规则简单java对象
一个中间对象,可以转化为PO、DTO、VO。
1 .POJO持久化之后==〉PO
(在运行期,由Hibernate中的cglib动态把POJO转换为PO,PO相对于POJO会增加一些用来管理数据库entity状态的属性和方法。PO对于programmer来说完全透明,由于是运行期生成PO,所以可以支持增量编译,增量调试。)
2 .POJO传输过程中==〉DTO
3 .POJO用作表示层==〉VO
PO 和VO都应该属于它。
BO :business object 业务对象
封装业务逻辑为一个对象(可以包括多个PO,通常需要将BO转化成PO,才能进行数据的持久化,反之,从DB中得到的PO,需要转化成BO才能在业务层使用)。
关于BO主要有三种概念
1 、只包含业务对象的属性;
2 、只包含业务方法;
3 、两者都包含。
在实际使用中,认为哪一种概念正确并不重要,关键是实际应用中适合自己项目的需要。
VO :value object值对象 / view object表现层对象
1 .主要对应页面显示(web页面/swt、swing界面)的数据对象。
2 .可以和表对应,也可以不,这根据业务的需要。
注 :在struts中,用ActionForm做VO,需要做一个转换,因为PO是面向对象的,而ActionForm是和view对应的,要将几个PO要显示的属性合成一个ActionForm,可以使用BeanUtils的copy方法。
DTO (TO) :Data Transfer Object数据传输对象
1 .用在需要跨进程或远程传输时,它不应该包含业务逻辑。
2 .比如一张表有100个字段,那么对应的PO就有100个属性(大多数情况下,DTO 内的数据来自多个表)。但view层只需显示10个字段,没有必要把整个PO对象传递到client,这时我们就可以用只有这10个属性的DTO来传输数 据到client,这样也不会暴露server端表结构。到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为VO。
DAO :data access object数据访问对象
1 .主要用来封装对DB的访问(CRUD操作)。
2 .通过接收Business层的数据,把POJO持久化为PO。