最近由於工作忙的原因,部落格更新的比較慢,在此給園子裡的朋友說聲抱歉。於是,我利用周末的時間寫了一份Spring.NET架構的綜合應用,希望這樣的實用型架構能受到大家的歡迎。
一、概括
此Demo使用的開發工具是:VS2010,資料庫任意,Silvelright版本是4.0。
Demo分為三層(Tier),資料庫,伺服器端,用戶端。其中,伺服器端又分為三層(Layer),持久層,服務層,門面層。
WCF以Windows服務作為宿主,用戶端使用Silverlight運行瀏覽器之外。
圖1
圖1是解決方案中包含的項目。其中,Server檔案夾下是伺服器端的代碼,Host檔案夾下是伺服器端的Windows服務宿主,Client檔案夾下是Silverlight應用程式。
二、技術點
WCF的Binding配置使用NetTcpBinding,是為了實現“回調”。
其中,伺服器端中,添加,修改,刪除資料時調用用戶端的回調:
Callback
private void ReceiveProduct(Product entity)
{
try
{
Parallel.ForEach(callBackList, (item) =>
{
try
{
item.ReceiveProduct(entity);
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
}
});
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
}
}
public void DeleteProduct(Guid id)
{
var entity = this.ProductManager.Get(id);
if (entity == null)
{
return;
}
this.ProductManager.Delete(entity);
try
{
Parallel.ForEach(callBackList, (item) =>
{
try
{
item.ClearProduct(id);
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
}
});
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
}
}
用戶端收到回調時處理該請求:
Client
public void Proxy_ReceiveProductReceived(object sender, ReceiveProductReceivedEventArgs e)
{
var list = this.grid.ItemsSource as ObservableCollection<Product>;
if (list == null)
{
return;
}
var entity = list.FirstOrDefault(f => f.ID == e.entity.ID);
if (entity == null)
{
list.Add(e.entity);
}
else
{
entity.Code = e.entity.Code;
entity.Name = e.entity.Name;
entity.BuyPrice = e.entity.BuyPrice;
entity.SellPrice = e.entity.SellPrice;
entity.QuantityPerUnit = e.entity.QuantityPerUnit;
entity.Remark = e.entity.Remark;
entity.Unit = e.entity.Unit;
}
}
public void Proxy_ClearProductReceived(object sender, ClearProductReceivedEventArgs e)
{
var list = this.grid.ItemsSource as ObservableCollection<Product>;
if (list == null)
{
return;
}
var entity = list.FirstOrDefault(f => f.ID == e.id);
if (entity == null)
{
return;
}
list.Remove(entity);
}
這樣多個用戶端的資料就保持一致了。
由於目前Spring.NET的OpenSessionInView僅適用於Web,所以我使用AOP攔截WCF的Contract介面實作類別,在調用前開啟SessionScope,調用後關閉SessionScope。這樣在同一請求中就實現了NHibernate的Session同步。
OpenSessionInViewModule
public class OpenSessionInViewModule : IMethodInterceptor
{
private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(OpenSessionInViewModule));
public object Invoke(IMethodInvocation invocation)
{
SessionScope sessionScope = new SessionScope("appSettings", typeof(SessionScope), false);
try
{
sessionScope.Open();
object obj = invocation.Proceed();
return obj;
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
logger.Error(ex);
return null;
}
finally
{
sessionScope.Close();
}
}
}
Windows服務的部署。
Host檔案夾下有兩個批處理(.bat)檔案:Install.bat和UnInstall.bat。分別為安裝和卸載Windows服務的命令。2.1所示。
圖2.1
Silverlight 4的跨越需要在http伺服器的80連接埠放置clientaccesspolicy.xml的跨域檔案,2.2所示。
圖2.2
這裡的http伺服器可以不為IIS,但是輸入欄位名+clientaccesspolicy.xml的時候必須能夠訪問到clientaccesspolicy.xml頁面。
clientaccesspolicy.xml
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*" />
</allow-from>
<grant-to>
<socket-resource port="4502-4534" protocol="tcp" />
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
三,運行效果
圖3.1
圖3.1是NHibernate自動表後的資料庫。
圖3.2
圖3.2是Silverlight應用程式的運行效果。
運行多個用戶端的效果,3.3所示。
圖3.3
點擊添加或者修改按鈕,彈出修改頁面(3.4所示)。然後點擊確定按鈕保持資料,由於是雙向通行,則兩個用戶端的資料保持一致(3.5所示)。
圖3.4
圖3.5
四、總結
該Demo是一個Spring.NET和NHibernate架構的綜合應用,實用於小型項目的公司專屬應用程式。此架構有較強的實用性,並在項目開發中達到“快速開發”的目的。希望愛好鑽研的朋友能夠下載My Code,並和我一起討論。
代碼下載
出處:http://www.cnblogs.com/GoodHelper/archive/2010/10/16/SpringNetFramework_Step2.html
歡迎轉載,但需保留著作權。