2014年7月29日 星期二

Universal Apps 的 Solution 結構

第一次建立 Universal App 的人大概會將 Shared Project 當成是一般的 Library 專案來使用,在一般的情況下使用的確沒有相異之處,開始感覺第一個特殊的功能大概是 Resource 可以直接放在 Shared 專案中,達到 Windows 及 Windows Phone 專案共用字串表、圖檔等效果,比起 Silverligt for Windows Phone 搭配一般的 Library Project 方便許多。

建立一個名為 UAPractice 的 Universal App 後,在 Shared Project 中加入 Assets 資料夾及 Shared.png 圖片,可以在 Windows 或 Windows Phone 專案中將它視為是同一個專案以 Source="Assets/Share.png" 這種方直接使用。

這種使用另一個 Project Resource 的方式在 Windows RT 時必須再加上 Project 名稱,例如 Source="LibraryProject/Assets/LibraryShare.png",在簡單的資源共享下 Shared Project 就如上面圖檔的例子一樣差異不大,但如果是加入 Library Reference 時觀念差異就出現了,一開始大概會依照直覺在 Shared Project 上按右鍵加入參考,這時會發現選單中並沒有加入參考的功能,這就是 Universal App 專案和一般專案觀念較不相同的部份。

舉一個最實用的例子來說,如果我們想要將資料庫的操作寫在 Shared Proejct 中讓 Windows 與 Windows Phone 專案共用相同的資料庫存取邏輯,理論上我們建立一個如下圖的方案結構。



這時理所當然的我們想要在 UAPractice.Shared 中加入一些操作 SQLite 的動作,舉例來說我加入一個 Session.cs 來做這件事

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Windows.Storage;
using SQLite;

namespace UAPractice
{
    class Session
    {
        public Session()
        {

        }

        public void LoadStorageSession()
        {
            String strDBPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "UAPractice.db");
            SQLiteConnection conn = new SQLiteConnection(strDBPath);
        }
    }

    [Table("session_table")]
    class StorageSession
    {
        [PrimaryKey, AutoIncrement, Column("id")]
        public int Id { get; set; }
        [Column("name")]
        public string Name { get; set; }
    }
}


在寫完 Session Class 之後會發現所有 SQLite 的類別一定都被標上紅線,這時只要在 Windows 專案及 Windows Phone 專案各自加上 SQLite 的參考即可,大概重點就是,為平台專案加入參考,Shared 專案就擁有該參考,兩個平台皆加入相同的參考,才能正常的編譯 Shared 專案,同樣以這個使用 SQLite 的專案為例,完成可編譯的設定後結構如下圖。


另一種狀況,如果某些 Library 只有提供 Windows Platform 的版本,或是某些功能我們只在 Windows Phone 的應用程式上實作,這種情況就不會為兩個專案都加入同樣的參考,這時就會碰到實作上的問題了。

在只加了其中一個專案的情況下,程式撰寫時編輯器不會回報任何錯誤,在編譯時編譯器卻會產生某一個平台專案沒有元件可參考的錯誤,這時有兩個方法,最簡單的方法是一行程式也不加,先將沒加入參考的專案先 Unload Project 再編譯,另一個就是要在 Shared Project 中使用 #if WINDOWS_PHONE_APP 或是 #if WINDOWS_APP 包住各自才需要用到的程式碼片段,以剛才寫的 Session.cs 為例,如果我不需要在 Windows Phone 的版本上實作資料庫功能,我可以把 Phone Project 中的 SQLite 參考移除,並將 Session.cs 改成這樣 (注意連 using 的部份也要包起來)

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Windows.Storage;
#if WINDOWS_APP
using SQLite;
#endif

namespace UAPractice
{
    class Session
    {
        public Session()
        {

        }

        public void LoadStorageSession()
        {
#if WINDOWS_APP
            String strDBPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "UAPractice.db");
            SQLiteConnection conn = new SQLiteConnection(strDBPath);
#endif
        }
    }
 
#if WINDOWS_APP
    [Table("session_table")]
    class StorageSession
    {
        [PrimaryKey, AutoIncrement, Column("id")]
        public int Id { get; set; }
        [Column("name")]
        public string Name { get; set; }
    }
#endif
}


沒有留言:

張貼留言