静态构造函数总是至多被调用一次吗?静态构造函数一定会被调用吗?看如下反例:
namespace ConsoleApplication1
{
class Program:A<float>
{
static Program()
{
Console.WriteLine("Class Program static construct invoked.");
}
static void Main(string[] args)
{
Console.WriteLine(B.SomeValue++);
Console.WriteLine(C.SomeValue++);
Console.WriteLine(D.SomeValue++);
Console.WriteLine(E.SomeValue++);
Console.WriteLine(E.SomeValue2++);
new F();
new F();
Console.ReadKey();
}
}
class A<T>
{
public static int SomeValue=0;
public A()
{
Console.WriteLine("Class A<{0}> dynamic construct invoked.", typeof(T).Name);
}
static A()
{
Console.WriteLine("Class A<{0}> static construct invoked.",typeof(T).Name);
}
}
class B : A<string>
{
static B()
{
Console.WriteLine("Class B static construct invoked.");
}
}
class C : A<int>
{
static C()
{
Console.WriteLine("Class C static construct invoked.");
}
}
class D : A<int>
{
static D()
{
Console.WriteLine("Class D static construct invoked.");
}
}
class E : A<float>
{
public static int SomeValue2 = 0;
static E()
{
Console.WriteLine("Class E static construct invoked.");
}
}
class F : A<bool>
{
public F()
{
Console.WriteLine("Class F dynamic construct invoked.");
}
static F()
{
Console.WriteLine("Class F static construct invoked.");
}
}
}
输出如下:
Class Programe static construct invoked.
Class A<String> static construct invoked.
0
Class A<Int32> static construct invoked.
0
1
Class A<Single> static construct invoked.
0
Class E static construct invoked.
0
Class F static construct invoked.
Class A<Boolean> static construct invoked.
Class A<Boolean> dynamic construct invoked.
Class F dynamic construct invoked.
Class A<Boolean> dynamic construct invoked.
Class F dynamic construct invoked.
对输出结果分析如下:
//程序运行实际上是Framework调用Program的Main静态方法,但不会实例化Program
Class Program static construct invoked.
//实际上静态成员并不支持继承,C#编译器会在底层将B.SomeValue翻译成A<string>.SomeValue
//所以被加载的不是B,而是A<string>
Class A<String> static construct invoked.
0
//同样此处C.SomeValue被翻译成A<int>.SomeValue
Class A<Int32> static construct invoked.
//诧异?被继承的SomeValue不是被“加加”了吗,为何此处还是0
0
//看到了吧,SomeValue确实被“加加”了,不过A<string>与A<int>属于不同的类型
//里面的SomeValue也是相互独立的
1
//E.SomeValue被翻译成A<float>.SomeValue
Class A<Single> static construct invoked.
0
//此处的E.SomeValue2远远本本的就是E.SomeValue2当然E的静态构造函数会被执行。
//现在我们才发觉B/C/D三者的静态构造函数都没被执行,原因呢,刚才也说了,实际上
//上面的B/C/D的引用在底层都被翻译成了A的封闭类,所以加载的并不是B/C/D本身,而是
//相应的封闭类
Class E static construct invoked.
0
//现在再来温习一下静态构造方法与构造方法的执行顺序
//因为new的是F,所以F首先被加载,进而执行F的静态构造
Class F static construct invoked.
//加载F后发现F是从A<bool>继承的,进而去加载A<bool>,于是A<bool>的静态构造被执行
Class A<Boolean> static construct invoked.
//首先执行基类的构造方法
Class A<Boolean> dynamic construct invoked.
//而后是F自己的构造方法
Class F dynamic construct invoked.
//此两句因为A<bool>与F以被加载,静态构造已被执行,因而直接按顺序从低往高调用构造方法
Class A<Boolean> dynamic construct invoked.
Class F dynamic construct invoked.
总结:
1.泛型类的各封闭类,属于不同的类,各自有自己独立的静态空间
2.静态成员实际上不支持继承,C#编译器在底层将实际的引用确定成静态成员定义者
3.静态构造函数不一定会被执行,因为有的类,在执行过程中不会被加载
4.静态构造函数确实是总是至多被调用一次,但是泛型类的静态构造要站在另一个角度考虑
5.类的构造函数执行顺序是自底而上
6.类的静态构造函数执行顺序是不能确定的,因为编程过程中,类的使用顺序是不定的,静态构造函数总是在类第一次被用到的地方执行
看了诸多关于ID问题的讨论后,决定用Guid结合插入时事件来实现ID唯一性。
实现如下(.NET3.5的自动属性):
//实体基类
public abstract class Entity{
public Guid ID{
get;set;
}
}
//汽车
public class Car:Entity{
public Person Owner{
get;set;
}
}
//人
//public class Person:Entity{
public string Name{
get;set;
}
}
以下是业务基类:
public abstract class BLLBase<T> : ICommonBLL<T> where T : Entity
{
//静态ObjectServer对象用以持有数据文件
protected static IObjectServer DBS;
//静态ObjectContainer对象,用于静态代码中的数据操作
protected static IObjectContainer DBC;
//DB4O的事件注册器
protected static IEventRegistry DBER;
//运行时的ObjectContainer实例
protected IObjectContainer DB;
/// <summary>
/// 静态构造用于打开ObjectServer及注册应用程序结束事件
/// </summary>
static BLLBase()
{
//BLLFactoryBase在BLLBase加载前要准备好ConnectionString
//此处在实际Factory被加载时会初始化ObjectServer
IConfiguration conf = Db4oFactory.NewConfiguration();
conf.BlockSize(8);
conf.ActivationDepth(2);
//初始化静态ObjectServer/ObjectClient及事件注册器
DBS = Db4oFactory.OpenServer(conf, Factory.ConnectionString, 0);
DBC = DBS.OpenClient();
DBER = EventRegistryFactory.ForObjectContainer(DBC);
DBER.Creating += new CancellableObjectEventHandler(BLLBase_Creating);
//进程结束时关闭ObjectServer
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
}
/// <summary>
/// 应用程序结束事件,用于关闭ObjectServer
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
static void CurrentDomain_ProcessExit(object sender, EventArgs args)
{
DBC.Close();
DBS.Close();
}
/// <summary>
/// 数据创建事件,自动生成唯一性标识
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
static void BLLBase_Creating(object sender, ObjectEventArgs args)
{
Model.Entity ent = args.Object as Entity;
if (ent != null)
ent.ID = Guid.NewGuid();
}
/// <summary>
/// 构造时打开连接
/// </summary>
public BLLBase()
{
DB = DBS.OpenClient();
}
/// <summary>
/// 不用时释放连接
/// </summary>
~BLLBase()
{
DB.Close();
}
//增删改查的基础实现省略
}
在进行插入操作时会引发BLLBase_Creating,会给实体对象的ID赋一个唯一的值。
但是在实际调试中插入后其他属性都有值,就是ID没有,但调试过程中确实看到Guid.NewGuid()的运行并被赋给ID。但却保存不了,近两个小时的折腾之后,却发现是.NET3.5自动属性搞的鬼。
原来DB4O保存的是对当前对象可见的域,而自动属性被编译器翻译后最终会成为如下形式:
public class Entity{
private Guid _ID;
public Guid ID{
get{return _ID;}
set{_ID=value;}
}
}
显然无论是Car还是Person从Entity继承来的_ID对他们来说都是不可见的,所以不会被保存。
明白以后就修改Entity的各个属性将私有域改为protected即可
母版页和内容页的执行顺序:
1.母版页中控件的Init;
2.内容页控件的Init;
3.母版页的Init;
4.内容页的Init;
5.内容页的Load;
6.母版页的Load;
7.内容页中控件的Load;
8.内容页的PreRender;
9.母版页的PreRender;
10.母版页控件的PreRender;
11.内容页中控件的PreRender
另:Page.DataBind()会引发子控件的DataBind(),母版页的Page.DataBind()会引发子页面的DataBind()
DataBind可做以下设计(按执行顺序书写):
母版页Init: 读取系统配置,设定母版空间DataSource 等
子页面Load: 设定子页面空间DataSource
模板页Load: 执行Page.DataBind();
安装好网卡后,安装 (最新版Ubuntu Server 9.04已集成wpasupplicant)
apt-get install wpasupplicant
生成配置文件:
wpa_passphrase SSID KEY > /etc/wpa_supplicant.conf
修改/etc/network/interfaces:
auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant.conf
(/etc/wpa_supplicant.conf 这个位置可以随便定)







