最近作了一個軟件,這個軟件不是網站,可是與HTML,AJAX等技術密切相關,也不是隻有單純的數據庫增刪改查,還涉及到線程協調,比較複雜的文本處理……數據庫
這樣的軟件,用OA,ERP的框架顯然是不合適的,由於這種軟件用不上權限管理,工做流這些技術。可是軟件又要操做數據庫。服務器
介於這些的特殊性,想來想去,仍是本身搭建一個輕量級的軟件框架是比較好的。app
一:C/S與B/S的選擇框架
1,我作的是一個購物網站的刷單軟件,有以下幾個方面的緣由,我選擇了C/S程序異步
a,刷單軟件須要長時間的運行,不定時,不間斷的去訪問購物網站。ide
b,有時候有多個線程的須要。工具
c,程序運行時,須要操做本地文件的權限,要把關鍵頁面截圖(如添加收藏,貨比三家)保存到本地,而後上傳到服務器。網站
d,C#的Httpresponse,HttpRequest對象運行在不一樣的電腦上,有不一樣的外網IP,若是作成網站,Httpresponse,HttpRequest永遠只是在服務器上運行,外網IP只有一個。ui
2,在桌面運用程序方面,我感受用WPF要比用WinForm好。this
a,WPF的UI作出的產品確定要比WinForm專業,這一點是誰都不可否認的。
b,WPF技術運用了XAML語法,這個比WinForm好用。
c,WPF能夠用到MVVM模式,這點WinForm是永遠都作不到的,而且MVVM有比較成熟的產品(MVVMLight, Caliburn.Micro,Prism)等產品
在這兒選用的是Caliburn.Micro框架,優勢在於有命名的自動匹配,發佈/訂閱的消息模式,IOC的解耦,我舉兩個例子說明一下吧:
例一,IOC建立對象
個人項目 Trade.WPFClient 要用到 Trade.WPFBusinessPart 的頁面,正常狀況下 Trade.WPFClient 要添加項目 Trade.WPFBusinessPart的引用。
可是用Caliburn.Micro是不用添加引用的。
只添要在引導程序中AppBootstrapper.cs中的配置加添加以下代碼:
protected override void Configure() { foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "Trade.*.dll")) { AssemblySource.Instance.Add(Assembly.LoadFile(file)); } var catalog = new AggregateCatalog( AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()); this.container = new CompositionContainer(catalog); var batch = new CompositionBatch(); batch.AddExportedValue<IWindowManager>(new WindowManager()); batch.AddExportedValue<IEventAggregator>(new EventAggregator()); batch.AddExportedValue(this.container); batch.AddExportedValue(catalog); this.container.Compose(batch); }
在使用的時候,用IOC的方式建立對象:
UserCenterViewModel userCenter = (UserCenterViewModel)IoC.Get<IUserCenter>(); bool? userCenterVal = IoC.Get<IWindowManager>().ShowDialog(userCenter);
根本就不用引用一個類庫,而後new一個對象。作到了高內聚,低耦合的原則。
例二:發佈/訂閱模式編
先要定義一個接口,個人項目是以 Trade.BaseInterface 這個類庫做爲個人接口庫類。
在發佈頁面:
方法一是同步UI發佈事件,
方法二是新開一個Task來發佈一個事件。也就是異步發佈事件。
而後在另一個頁面接收這個發佈的事件:
這樣就實現了兩個類庫之間互相不添加引用的狀況下,把消息通知給另一個類庫。
二:數據庫的持久化操做
數據庫持久化操做經歷了不少階段,
1,SqlHelper階段
2,enterprise library階段
3,Ibatis,Dapper階段
4,Linq, Nhibernate, EntityFramework階段。
這幾種操做,我在實戰項目中都使用過,猶其是EntityFramework,無論是Code Frist 模式,Mode First模式,仍是Data First模式,好幾年前就用在項目中作過比較了。
可是我最承認的仍是Dapper。
來一段碼:
/// <summary> /// 根據用戶ID獲取用戶的相關信息 /// </summary> /// <param name="dContext"></param> /// <param name="userID"></param> /// <returns></returns> public TradeUserModel GetTradeUserByUserID(DataContextBase dContext, String userID) { TradeUserModel result = default(TradeUserModel); String querySql = @"select * from TradeUser where UserID = @UserID; select ROW_NUMBER() over (order by DoBindingDTime desc) as RowNo, * from Member where IsDelete = '0' and UserID = @UserID; select * from Member where IsDelete = '0' and IsCurrent = '1' and UserID = @UserID "; var multi = dContext.Connection.QueryMultiple(querySql, new { UserID = userID }, dContext.Transaction); result = multi.Read<TradeUserModel>().FirstOrDefault(); List<MemberModel> memberList = multi.Read<MemberModel>().ToList(); MemberModel currentMember = multi.Read<MemberModel>().FirstOrDefault(); result.MemberList = new ObservableCollection<MemberModel>(memberList); MoneyRepository moneyRepository = new MoneyRepository(); decimal totalMoneyIn = moneyRepository.GetBusinessMoneyByUserID(dContext, userID, "In", new string[] { "RechargeMoney", "" }); decimal totalMoneyOut = moneyRepository.GetBusinessMoneyByUserID(dContext, userID, "Out", new string[] { "TakeMoney", "TaskOut", }); decimal totalTransferMoneyIn = moneyRepository.GetBusinessMoneyByUserID(dContext, userID, "In", new string[] { "TransferMoneyIn", "" }); decimal totalTransferMoneyOut = moneyRepository.GetBusinessMoneyByUserID(dContext, userID, "Out", new string[] { "TransferMoneyOut", "" }); result.TotalEnableMoney = totalMoneyIn + totalMoneyOut; result.TotalNotEnableMoney = 0; result.TotalTransferMoney = totalTransferMoneyIn + totalTransferMoneyOut; result.CurrentMember = currentMember; // currentMember ?? new MemberModel(); return result; }
我一段Sql執行了三個查詢,用QueryMultiple取得不一樣的查詢結果,最神奇的地方,是查詢出來的字段,不用手動賦值,Dapper能夠自動實現。好比
public List<InvitationModel> GetInvitationCollectionByOwner(DataContextBase dContext, InvitationModel invitationData) { List<InvitationModel> result = default(List<InvitationModel>); String querySql = @"select ROW_NUMBER() over (order by CreateDTime desc) as RowNo , tu1.UserName as OwnerInfoName, tu2.UserName as ComputerUniqueName, i.* from Invitation i left join TradeUser tu1 on i.OwnerInfo = tu1.UserID left join TradeUser tu2 on i.ComputerUnique = tu2.UserID where OwnerInfo = @OwnerInfo;"; result = dContext.Connection.Query<InvitationModel>(querySql, invitationData, dContext.Transaction).ToList(); return result; }
這樣的我查詢結果就直接 賦值給 InvitationModel 類了。
三:項目中實體對象的共用
理論上,應該要申明一個類與表的字段對應
若是是用WCF做爲通訊傳輸,還得聲明一個DataContract 數據契約類
若是是用的MVVM框,還得要有一個ViewModel類
三個類這間,要轉換賦值,有相似 automapper 這樣的工具,可是我仍是不建議轉換去,轉換來的。
我直接把這個三個不一樣地方的類給共用起來。
好比個人實體類以下:
[DataContract] public class LogModel : NotifyPropertyChanged { private Guid _logID; [DataMember] public Guid LogID { get { return _logID; } set { _logID = value; OnPropertyChanged("LogID"); } } ……
1,能夠運做WCF的數據契約傳輸,
2,還能夠做爲MVVM的ViewModel
3,還能夠與數據庫字段在ORM時相互映射
一箭三雕啊
結語:
這個項目還運用到了不少技術,如如線程的管理,解析網頁(網頁異步加載情下)是怎麼處理的?
等下一篇博客再說。
若是對這個軟件感受興趣的,可看上一篇博客。謝謝!