1. 把所有的资源放在一个或多个DLL里, 就象游戏软件把所有的图片做一个资源包, 所有的音效做一个资源包的做法类似, 好处是可以减少主程序的大小, 另外把业务代码根据需要放在一个或多个DLL里, 最终是能够提升软件自动升级的效率, 避免无意义的下载流量, 当然, 为了避免出现DLL Hell, 最好是把所有的DLL加上Strong Name
/**/
/// <summary>
/// 从资源DLL中取得需要的资源
/// </summary>
public static Stream GetResource( string fileName)
{
Stream stream = null;
Type resourceType = typeof(ResourceManager); //ResourceManager是资源DLL中定义的一个DummyClass
string resourceName = resourceType.Namespace + "." + fileName.Replace("\\", ".");
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(resourceType);
if (assembly == null)
throw new Exception("无法装载资源文件: " + resourceType.Namespace + ".dll");
stream = System.Reflection.Assembly.GetAssembly(resourceType).GetManifestResourceStream(resourceName);
if (stream == null)
throw new Exception("无法取得资源: " + fileName);
return stream;
}
/// 从资源DLL中取得需要的资源
/// </summary>
public static Stream GetResource( string fileName)
{
Stream stream = null;
Type resourceType = typeof(ResourceManager); //ResourceManager是资源DLL中定义的一个DummyClass
string resourceName = resourceType.Namespace + "." + fileName.Replace("\\", ".");
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(resourceType);
if (assembly == null)
throw new Exception("无法装载资源文件: " + resourceType.Namespace + ".dll");
stream = System.Reflection.Assembly.GetAssembly(resourceType).GetManifestResourceStream(resourceName);
if (stream == null)
throw new Exception("无法取得资源: " + fileName);
return stream;
}
2. 把应用程序的主入口点的代码放到一个新单元的启动类里, 好处是与主窗体的代码分开, 流程更加清晰
3. 用执行文件的版本号作为系统的版本号,避免出现多个定义的地方
Assembly assembly
=
Assembly.GetExecutingAssembly();
object [] assemblyTitleAttributes = assembly.GetCustomAttributes( typeof (AssemblyTitleAttribute), false );
if (assemblyTitleAttributes.Length > 0 )
title = (assemblyTitleAttributes[ 0 ] as AssemblyTitleAttribute).Title;
version = assembly.GetName().Version.ToString();
object [] assemblyTitleAttributes = assembly.GetCustomAttributes( typeof (AssemblyTitleAttribute), false );
if (assemblyTitleAttributes.Length > 0 )
title = (assemblyTitleAttributes[ 0 ] as AssemblyTitleAttribute).Title;
version = assembly.GetName().Version.ToString();
4.有时需要统一设置窗体上控件的属性,作界面上的运行期绑定,下面提供一个返回所有控件的函数
/**/
/// <summary>
/// 取得指定容器上的全部子控件
/// </summary>
public static Control[] GetAllControls(Control ctrl)
{
ArrayList allControls = new ArrayList();
Queue queue = new Queue();
queue.Enqueue(ctrl.Controls);
while( queue.Count > 0 )
{
Control.ControlCollection
controls = (Control.ControlCollection)queue.Dequeue();
if( controls == null || controls.Count == 0 )
continue;
foreach( Control control in controls )
{
allControls.Add(control);
queue.Enqueue(control.Controls);
}
}
return (Control[])allControls.ToArray(typeof(Control));
}
/// 取得指定容器上的全部子控件
/// </summary>
public static Control[] GetAllControls(Control ctrl)
{
ArrayList allControls = new ArrayList();
Queue queue = new Queue();
queue.Enqueue(ctrl.Controls);
while( queue.Count > 0 )
{
Control.ControlCollection
controls = (Control.ControlCollection)queue.Dequeue();
if( controls == null || controls.Count == 0 )
continue;
foreach( Control control in controls )
{
allControls.Add(control);
queue.Enqueue(control.Controls);
}
}
return (Control[])allControls.ToArray(typeof(Control));
}
5.消息机制,写Windows程序,很有可能需要自定义消息加以处理
protected
override
void
DefWndProc(
ref
System.Windows.Forms.Message m)
{
switch(m.Msg)
{
case CM_MYMESSAGE:
//Do My Business
break;
default:
base.DefWndProc(ref m);
break;
}
}
{
switch(m.Msg)
{
case CM_MYMESSAGE:
//Do My Business
break;
default:
base.DefWndProc(ref m);
break;
}
}
private
const
int
CM_CUSTOMMESSAGE
=
0x1600
;
/**/ /// <summary>
/// 自定义消息
/// </summary>
public const int CM_MYMESSAGE = CM_CUSTOMMESSAGE + 1 ;
[DllImport( " User32.dll " ,EntryPoint = " SendMessage " )]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport( " User32.dll " ,EntryPoint = " PostMessage " )]
public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
/**/ /// <summary>
/// 自定义消息
/// </summary>
public const int CM_MYMESSAGE = CM_CUSTOMMESSAGE + 1 ;
[DllImport( " User32.dll " ,EntryPoint = " SendMessage " )]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport( " User32.dll " ,EntryPoint = " PostMessage " )]
public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
6. 调用Jet Engine压缩Access数据库
/**/
/// <summary>
/// 压缩数据库
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="newFileName">文件名</param>
public static bool CompactDatabase( string fileName, string newFileName)
{
bool result = false;
//如果要压缩的数据库打开的话,先关闭之
string TempFile;
if (newFileName == String.Empty)
TempFile = Path.GetTempFileName();
else
TempFile = newFileName;
try
{
object[] oParams;
object objJRO = Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine"));
oParams = new object[] {TConnection.ConnectionString(fileName), "Provider=Microsoft.Jet.OLEDB.4.0;Data" + " Source=" + TempFile + ";Jet OLEDB:Engine Type=5"};
objJRO.GetType().InvokeMember("CompactDatabase", System.Reflection.BindingFlags.InvokeMethod, null, objJRO, oParams);
if (newFileName == String.Empty)
{
File.Delete(fileName);
File.Move(TempFile, fileName);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(objJRO);
objJRO = null;
result = true;
}
finally
{
//如果有必要的话,恢复数据库连接
}
return result;
}
/// 压缩数据库
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="newFileName">文件名</param>
public static bool CompactDatabase( string fileName, string newFileName)
{
bool result = false;
//如果要压缩的数据库打开的话,先关闭之
string TempFile;
if (newFileName == String.Empty)
TempFile = Path.GetTempFileName();
else
TempFile = newFileName;
try
{
object[] oParams;
object objJRO = Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine"));
oParams = new object[] {TConnection.ConnectionString(fileName), "Provider=Microsoft.Jet.OLEDB.4.0;Data" + " Source=" + TempFile + ";Jet OLEDB:Engine Type=5"};
objJRO.GetType().InvokeMember("CompactDatabase", System.Reflection.BindingFlags.InvokeMethod, null, objJRO, oParams);
if (newFileName == String.Empty)
{
File.Delete(fileName);
File.Move(TempFile, fileName);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(objJRO);
objJRO = null;
result = true;
}
finally
{
//如果有必要的话,恢复数据库连接
}
return result;
}
7. 程序中嵌入WebBrowser, .NET封装的AxWebBrowser的功能实在是够弱的,下面2篇文章基本上包括了设置WebBrowser的方方面面
http://icebird.cnblogs.com/articles/403056.html
http://icebird.cnblogs.com/articles/403031.html
by the way, CodeRush for VS.NET 和 Refactor! Pro for VS.NET真的很好用,不愧是DevExpress出品