Visual Studio - Shared Project v.s. Class Library Project

當我們程式寫久了就會開始整理共用的程式碼,限量通常都是寫成 Class Library,之後只要引用進來就可以重覆利用。Visual Studio 從 VS2015 開始就提供一個新的 Project 格式,叫做 Shared Project。Shared Project 故名思義就是存放共用程式碼的 Project,本篇就是要來介紹這個功能。

相信寫過 Class Library 的朋友們都知道,Class Library 的原理就是把一個眾多 Class 的集合或模組 Compile 成一個 Assembly(Dll檔),其他專案要使用到這些 Class 的功能時只要將該 Assembly 引入後就可以使用了,或者是將該 Class Library 的專案加入參考也可以。

Shared Project 就類似 Class Library,他也是可以將許多可以共用的 Class 集合或模組放在同一個 Project 中集中管理,其他專案要使用時必須透過加入參考的方式把 Shared Project 引入後就可以直接使用。但比較不同的是,Compile 的時候會將使用到的 Shared Project 的程式碼載入進去一起 Compile 成為該 Project Assembly 的一部份。也就是說 Shared Project 不會被單獨 Compile 成一個 Assembly,因為它 Shared 的是程式碼,我們直接以實際操作狀況來看看 Shared Project 如何運作的:

首先,限量建立了一個 Solution,有一個 ConsoleApp,接著限量加入一個名稱為 SharedCode 的 Shared Project。

撰寫完共用程式碼(ColorConsoleWriter)後,我在 ConsoleApp 專案加入 SharedCode 的參考。
SharedCode => ColorConsoleWriter.cs

using System;

namespace SharedCode
{
    public static class ColorConsoleWriter
    {
        private static class LevelBase
        {
            public static void Write(string value)
            {
                Console.Write(value);
                Console.ForegroundColor = ConsoleColor.Gray;
            }

            public static void WriteLine(string value)
            {
                Console.WriteLine(value);
                Console.ForegroundColor = ConsoleColor.Gray;
            }
        }

        public static class Trace
        {
            static Trace()
            {
                Console.ForegroundColor = ConsoleColor.White;
            }

            public static void Write(string value) => LevelBase.Write(value);

            public static void WriteLine(string value) => LevelBase.WriteLine(value);
        }

        public static class Debug
        {
            static Debug()
            {
                Console.ForegroundColor = ConsoleColor.Green;
            }

            public static void Write(string value) => LevelBase.Write(value);

            public static void WriteLine(string value) => LevelBase.WriteLine(value);
        }

        public static class Info
        {
            static Info()
            {
                Console.ForegroundColor = ConsoleColor.Blue;
            }

            public static void Write(string value) => LevelBase.Write(value);

            public static void WriteLine(string value) => LevelBase.WriteLine(value);
        }

        public static class Warn
        {
            static Warn()
            {
                Console.ForegroundColor = ConsoleColor.DarkYellow;
            }

            public static void Write(string value) => LevelBase.Write(value);

            public static void WriteLine(string value) => LevelBase.WriteLine(value);
        }

        public static class Error
        {
            static Error()
            {
                Console.ForegroundColor = ConsoleColor.Red;
            }

            public static void Write(string value) => LevelBase.Write(value);

            public static void WriteLine(string value) => LevelBase.WriteLine(value);
        }
    }
}
ConsoleApp => Program.cs

using System;
using SharedCode;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            ColorConsoleWriter.Trace.WriteLine("Trace");
            ColorConsoleWriter.Debug.WriteLine("Debug");
            ColorConsoleWriter.Info.WriteLine("Info");
            ColorConsoleWriter.Warn.WriteLine("Warn");
            ColorConsoleWriter.Error.WriteLine("Error");

            Console.ReadLine();
        }
    }
}

執行結果:

來看看加入 Shared Project 後的 Compile 結果:

上圖可以看到我們 Compile 出來只有一個 ConsoleApp 的 Assembly,那是因為 Compiler 把 SharedCode 的程式碼包進去了。

再來,我們建立一個名稱為 SharedLib 的 Class Library 來比較看看:

然後撰寫一樣的 ColorConsoleWriter 程式碼在裡面,並在 ConsoleApp 加入 SharedLib 的參考後並執行。
執行結果會是一樣的,但是看看編譯除來的結果,最後會有兩個 Assembly,分別為 ConsoleApp 與 SharedLib。

看完了實際實驗結果,你一定想說到底差在哪。其實兩者各有優缺點。Class Library 因為可以獨立 Compile 成一個 Assembly,假如我不想提供 Source Code,那我就可以直接提供 Assembly 就好了。如果以提供 Assembly 的方式,有另外一點好處,就是當我需要修改 Class Library 的程式碼時,修改後只需要重新 Compile 這個 Library 就好了,而不用像 Shared Project 那樣全部都 Compile。

用 Shared Project 也是有優點的,不然也不會多這個功能出來,比如說,對各平台的適應性來說, Shared Project 是特別高的,有時候我們有多個平台的專案要使用到相同的程式,如果用 Class Library 的話,因為有些平台可能不吃 Dll 檔,所以就沒辦法用了。或者有時候 Class Library 的 .Net 版本和平台不相容時,也是無法使用(但現在可以使用 .Net Standard,所以增強了相容性)。而且 Class Library 限定只能放 C# 或 VB 的程式。相對的,Shared Project 的彈性就比較高了,它可以在同一個 Project 裏頭包含許多種類型的程式碼,類如:Typescript, Javascript, C#, VB, XAML, HTML ... 等,就像是程式碼的儲藏庫。因為它引用的是程式碼,所以 Shared Projet 一開始在建立的時候也沒有分哪個平台哪個版本,下面再用一個實際操作來看看如何在不同類型的專案上引用 Shared Project:

我們在上面範例的 SharedCode 裏頭加入 echo.ts 檔,然後在我們建立的 NodejsConsoleApp 加入 SharedCode 的參考,然後用 import 的方式引入,如下:

SharedCode => echo.ts
export class Echo {
    static greeting(): void {
        console.log('Hello World!');
    }
}
NodejsConsoleApp => app.ts
import { Echo } from '../SharedCode/echo';

Echo.greeting();

執行結果:

看完了上面的實際範例後是不是覺得很棒,以後就直接開一個 Shared Project 來存放可以重複利用的程式碼,並建立各種程式語言的目錄來分類存放,至少做了一個簡單的知識管理。對將來的程式開發速度會有一定的幫助。




參考來源:
C# Corner - Shared Project : An Impressive Feature of Visual Studio 2015 Preview





留言