文章出處

一,以實際案例引入阿里云的運用

好多人都在玩概念,玩什么概念,比如工業4.0

什么叫工業4.0,簡單一點理解就是 “互聯網” + “制造”(互聯網+)。再通俗一些的理解就是“互聯網”做電商銷售,“制造”就是傳統生產。

最終做到有了訂單才生產,真正做到了按需生產,解決了企業物料損耗,庫存堆積等問題。

比如:以印刷廠為案例來說工業4.0,一個印刷廠,客戶下單才印刷,不能先印刷一堆東西堆在庫存里吧!

先可以看一個流程示意圖:

1,客戶通過銷售平臺下單(印刷數量,規格,付款,以及上傳需要印刷的文件,與普通電商銷售平臺的區別體現在上傳文件這兒)

2,通過一個服務(ESB),把客戶的訂單信息,文件數據流轉到印刷廠的生產系統。

今天我重點要說的就是ESB服務,怎樣高效穩定的把文件從銷售平臺轉到生產系統。

需求:

1,因為訂單量大,每天有2至3T的文件從銷售平臺流向生產系統。

2,這些文件至少要保存一個月左右,有可能返工印刷(算下來企業最小極限要有100個T的存儲服務器)。

經過多方面的考慮,建議選擇阿里云的存儲。

二,阿里云存儲OSS的開發

1,支持目錄結構的文件,普通文件的傳輸。

2,銷售平臺端上傳文件到阿里云服務器,支持多線程的(分塊上傳,分塊校驗,斷點續傳,重試,文件MD5值檢驗,進度,速度,需要用時的顯示)

3,ESB服務從阿里云服務器下載文件,支持多線程的(分塊下載,分塊校驗,斷點續傳,重試,文件MD5值檢驗,進度,速度,需要用時的顯示)

4,把下載的文件經過一系統的預檢,處理,最終拷貝到生產系統。

5,反饋文件處理結果到銷售平臺,生產系統。

這幾個需求促使我們有必要開發一個個性化的阿里云客戶端,這個客戶端已經滿足了我上面說的的需求。

 三,具體開發介紹

 3.1程序目錄結構的介紹

 

先上圖,再來解釋。

不管會不會寫程序的,只要是懂點IT的,聊到程序時,都會聊到點架構。落伍一些的就聊“三層架構”,牛批一些的就聊“分布式架構”,在博客園里都能找到上十種的架構。

在這兒,我就不畫架構圖了,就以目錄來說我的程序架構。

顯而易見:

這個程序最底層的架構:服務端  + 客戶端。

服務端:數據庫的持久化操作,和一些公用接口,比如獲取服務器時間服務。

客戶端:UI的數據呈現,下載,文件處理等的業務邏輯。

其中客戶端又包含了一個UI框架:

這個框架是MVVM模式,相當于B/S結構中的MVC。

這個UI框架:

1,實現了XAML與C#代碼的分離

2,實現在IOC的控制反轉的模式

3,利用觀察者模板實現了模塊與模塊之間的解耦

3.2關鍵核心的架構代碼:

代碼片段1:

因為整個程序,各個程序之間互相不添加引用,只要在生成項目的時候用這樣的命令把dll文件拷貝到UI框架目錄下即可

xcopy $(TargetPath) $(SolutionDir)FileTransfer.Client\bin\Debug /y
xcopy $(TargetPath) $(SolutionDir)FileTransfer.Client\bin\Release /y

具休操作如圖所示:

 代碼片段2:

因為UI啟動程序不添加各dll的引用,目的是使每個功能模板之間的解耦合,所以在啟動程序時,需要添加一段引導代碼:

    public class AppBootstrapper : BootstrapperBase
    {
        private CompositionContainer container;

        public AppBootstrapper()
        {
            Initialize();
        }

        protected override void BuildUp(object instance)
        {
            this.container.SatisfyImportsOnce(instance);
        }

        /// <summary>
        ///     By default, we are configured to use MEF
        /// </summary>
        protected override void Configure()
        {
            foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.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);
        }

        protected override IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return this.container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
        }

        protected override object GetInstance(Type serviceType, string key)
        {
            var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
            var exports = this.container.GetExportedValues<object>(contract);

            if (exports.Any())
            {
                return exports.First();
            }

            throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            //var startupTasks =
            //    GetAllInstances(typeof(StartupTask))
            //    .Cast<ExportedDelegate>()
            //    .Select(exportedDelegate => (StartupTask)exportedDelegate.CreateDelegate(typeof(StartupTask)));

            //startupTasks.Apply(s => s());
            DisplayRootViewFor<FileTransfer.Interface.IShell>();
            //base.OnStartup(sender, e);
        }
    }
View Code

這個引導代碼有一個很關鍵的地方,我把它提煉出來:

    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFile(file));
    }

就是要把需要的dll,通過一定規則的匹配模式把dll放入到程序的容器中。通過以下的代碼來獲取實例:

    object obj = IoC.Get<IRetrievePwd>();
    IoC.Get<IWindowManager>().ShowDialog(obj);

 代碼片段3:

觀察者模式的實現:

觀察者模式,首先,我們肯定要明白有兩個對象,一個是發布信息,一個是接收信息,同時還需要一個契約。如下代碼:

    PublishTaskViewModel ptvm = (PublishTaskViewModel)IoC.Get<IPublishTask>();
    ptvm.TaskViewData = taskData;
    ptvm.OperateType = OperateTypeEnum.Edit;
    _eventAggregator.PublishOnUIThread(new ShowMainContentEvent { ContentModel = ptvm });

其中:
IPublishTask  就是我定義的觀察者模式契約。

PublishOnUIThread  就是我發出一條消息,發出消息的模式有很多種,如下圖:

訂閱對象要實現:

    this._eventAggregator.Subscribe(this);

再用這樣的方法接收信息:

    public void Handle(ShowMainContentEvent message)
    {

    }

 四,結語

一言難盡,還有很多很多要寫的地方。這個給公司開發的代碼,又不能共享,只能多分享。

如果大家想學習我這套開發框架構,我也有類似的開源程序,麻煩翻一翻我的博客,有一篇程序寫了一個軟件,就是用的這個架構。并且UI做的比這個更靚哦!

如果大家感覺贊,就動動手指幫我點一下推薦吧!謝謝您能看到這兒。

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()