XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2017/09/29

在 Visual Studio 2017 上,安裝 .NET Standard 2.0 標準類別庫支援

了解更多關於 [Xamarin.Android] 的使用方式
了解更多關於 [Xamarin.iOS] 的使用方式
了解更多關於 [Xamarin.Forms] 的使用方式
了解更多關於 [Hello, Android:快速入門] 的使用方式
了解更多關於 [Hello, iOS – 快速入門] 的使用方式
了解更多關於 [Xamarin.Forms 快速入門] 的使用方式

  • 首先,請先將您的 Visual Studio 2107 升級到 15.3 以上的版本
  • 請安裝指定 SDK
  • 請依照指示,繼續安裝
    .NET Core 2.0 Install
    .NET Core 2.0 Install
    .NET Core 2.0 Install
  • 完成安裝

進行檢測

  • 開啟 Visual Studio 2017
  • 選擇功能表 檔案 > 新增 > 專案 > 已安裝 > Visual C# > .NET Standard > 類別庫 (.NET Standard)
    建立一個 .NET Standard 標準類別庫
    .NET Core 2.0 Install
  • 滑鼠右擊該專案的節點,選擇 屬性
    點選 目標 Framework 的下拉選單控制項,從這裡,你就可以切換使用 .NET Standard 2.0
    .NET Core 2.0 Install

2017/09/28

利用 UnhandledException 與 UnobservedTaskException 找出 Xamarin 的 "An unhandled exception occured" 錯誤問題

我們在進行 Xamarin.Forms 專案開發的時候,偶而會遇到這樣的例外錯誤訊息 An unhandled exception occured
unhandled exception1

了解更多關於 [Xamarin.Android] 的使用方式
了解更多關於 [Xamarin.iOS] 的使用方式
了解更多關於 [Xamarin.Forms] 的使用方式
了解更多關於 [Hello, Android:快速入門] 的使用方式
了解更多關於 [Hello, iOS – 快速入門] 的使用方式
了解更多關於 [Xamarin.Forms 快速入門] 的使用方式

可是,從這個畫面上,也看不出問題發生在哪裡,若我們點選 複製詳細資料 ,則會得到這樣的內容:An unhandled exception occured. 發生
結果,還是一樣,無法看到何有幫助的訊息。
在我們這裡,可以使用 C# 內建的類別 應用程式定義域 (Application Domain) 裡面的一個事件 UnhandledException;一旦你訂閱了這個事件,並且應用程式發生了沒有捕捉到的任何例外異常,這個訂閱的事件方法,將會被呼叫執行。
這個事件會接收一個客製化的事件引數類別 UnobservedTaskExceptionEventArgs 我們可以從這個參數中,得到真正發生例外異常的情況。
若想要使用這樣的功能,您需要在 Xamarin 原生專案的進入點加入訂閱這個事件,底下為在 Android 平台專案下的 MainActivity.cs的程式碼使用範例。
protected override void OnCreate(Bundle bundle)
{
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
    TabLayoutResource = Resource.Layout.tabs;
    ToolbarResource = Resource.Layout.toolbar;

    base.OnCreate(bundle);

    global::Xamarin.Forms.Forms.Init(this, bundle);
    LoadApplication(new App(new AndroidInitializer()));
}

private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
    throw new NotImplementedException();
}

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    throw new NotImplementedException();
}
所以,你可以在 CurrentDomain_UnhandledException 設定一個中斷點,並且執行這個有問題的專案,若看到 An unhandled exception occured 這個錯誤訊息出現,則按下 F5 繼續來執行,直到在你剛剛設定的中斷點停下來;這個時候,你就可以查看 e 這個參數值,看到問題原因說明了,在這個範例中,我們看到的是 Master and Detail must be set before using a MasterDetailPage
unhandled exception1
unhandled exception1
此時,我們開啟 MasterDetailPage.xaml 檔案,您就會知道問題出在哪裡了。
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
                  prism:ViewModelLocator.AutowireViewModel="True"
                  x:Class="PrismUnityApp4.Views.MDPage">

</MasterDetailPage>

2017/09/25

.NET Framework / PCL 可攜式類別庫 / .NET Standard 標準類別庫 之中繼套件與類型轉送 深入探究

在這裡,我們透過 IL 中繼語言的反組譯工具 ILSpy 來查看這三個 .NET 生態環境的內容。

.NET Framework

我們使用 ILSpy 工具,打開 C:\Windows\Microsoft.NET\Framework\v4.0.30319 目錄,找到 mscorlib.dll這個檔案
接著展開其 mscorlib 節點,接著再展開 System.Collections.Generic 節點,就會看到 List<T> 節點,點擊這個節點,就會看到這個類別的原始 C# 原始程式碼。

PCL 可攜式類別庫

在這裡,我們使用 PCL Profile259 這個版本
我們使用 ILSpy 工具,打開 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile259\ 目錄,這裡就是 Profile 259 會使用到的類別庫組件所在位置,找到 System.Collections.dll 這個檔案
這個位置,可以從 Visual Studio 中,打開任意一個 PCL 可攜式專案,點選 參考 > .NET 節點,從屬性視窗的 路徑 中,就可以查到,如下圖所示
接著展開其 System.Collections 節點,接著再展開 System.Collections.Generic 節點,就會看到 List<T> 節點,點擊這個節點,就會看到這個類別的原始 C# 原始程式碼。
不過,在這裡,似乎你只看到了這個 List 類別的成員定義,而成員的方法似乎都沒有實做出來。
讓我們繼續使用 ILSpy 工具,打開 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile259\ 目錄,這裡就是 Profile 259 會使用到的類別庫組件所在位置,找到 mscorlib.dll 這個檔案
當你點選剛剛開啟的 mscorlib.dll 的 mscorlib 節點,從右邊分割視窗中,您會看到這個敘述 [assembly: TypeForwardedTo(typeof(List<>))] 這表示,在執行時期,若你的專案中有使用這個 List 的泛型型別,則真正實作的組件,將不會在這個組件內定義,而是使用了 Type Forwarding 類型轉送 技術,需要到其他的組件上來找到這個類別的實作定義。根據微軟官方文件上的描述:型別轉送可讓您將某種型別移到其他組件,而不需重新編譯使用原始組件的應用程式

.NET Standard 標準類別庫

在這裡,請先下載 NETStandard.Library NuGet 套件到本機上,使用 zip 解壓縮工具,就可以解開這個 netstandard.library.2.0.0.nupkg 壓縮檔案。
當你在 Visual Studio 內,打開任意 .NET Standard 標準類別庫,就會看到如下圖
.NET Standard 標準類別庫
我們使用 ILSpy 工具,打開解壓縮 (netstandard.library.2.0.0.nupkg 壓縮檔案) 後的目錄 netstandard.library.2.0.0.nupkg\build\netstandard2.0\ref ,這裡就是 NETStandard.Library 會使用到的類別庫組件所在位置,找到 netstandard.dll 這個檔案
接著展開其 netstandard 節點,接著再展開 System.Collections.Generic 節點,就會看到 List<T> 節點,點擊這個節點,就會看到這個類別的原始 C# 原始程式碼。
不過,在這裡,似乎你只看到了這個 List 類別的成員定義,而成員的方法似乎都沒有實做出來。
讓我們繼續使用 ILSpy 工具,打開解壓縮 (netstandard.library.2.0.0.nupkg 壓縮檔案) 後的目錄 netstandard.library.2.0.0.nupkg\build\netstandard2.0\ref,這裡就是 NETStandard.Library 會使用到的類別庫組件所在位置,找到 mscorlib.dll 這個檔案
當你點選剛剛開啟的 mscorlib.dll 的 mscorlib 節點,從右邊分割視窗中,您會看到這個敘述 [assembly: TypeForwardedTo(typeof(List))] 這表示,在執行時期,若你的專案中有使用這個 List 的泛型型別,則真正實作的組件,將不會在這個組件內定義,而是使用了 Type Forwarding 類型轉送 技術,需要到其他的組件上來找到這個類別的實作定義。根據微軟官方文件上的描述:型別轉送可讓您將某種型別移到其他組件,而不需重新編譯使用原始組件的應用程式

總結

從上面的檢測過程,我們可以知道,不論 PCL 或者 .NET Standard 這兩個,他們使用的核心技術原則上是相同的,只不過對於中繼套件的使用方式與可以使用那些平台的 API 的規劃設定方式不同。
在 .NET Standard,中繼套件 (原始程式碼) 描述定義 (部分) 一個或多個 .NET 標準程式庫版本的程式庫集合,並且,以 NuGet 套件散發並由 NETStandard.Library 中繼套件參考的參考組件;而 PCL 的中繼套件則是存在於本機上的某個目錄中,這是隨著你的 Visual Studio 安裝的同時,也就會安裝進去的。
+

關於最後真正平台要使用各 API 實作,則是使用 Type Forwarding 類型轉送 技術,在執行階段,動態的進行使用真正實作的組件。

參考資料

2017/09/24

了解 .NET 標準類別庫 (.NET Standard) 的 Type Forwarding 運作情形(模擬演練)

在 .NET 標準類別庫 (.NET Standard Class Library) 裡面,使用到一個核心技術,那就是 Type Forwarding。
我們在這裡將會透過實際演練過程,讓您體驗出何謂 Type Forwarding。

準備專案

在這裡,建立一個 .NET Framework 類別庫,我們命名為:MyLibAssemblyA,這個類別庫內,僅有一個類別宣告,如下所示:
namespace TypeForward
{
    public class Foo
    {
    }
}
接著,我們建立一個 .NET Framework 可執行的專案,我們命名為:TypeForward,並且在這個專案內,使用加入參考功能,將類別庫 MyLibAssemblyA 加入到這專案內,這個可執行專案的程式碼如下:
using System;

namespace TypeForward
{
    class Program
    {
        static void Main(string[] args)
        {
            Foo foo = new Foo();
            Console.WriteLine(typeof(Foo).AssemblyQualifiedName);
            Console.WriteLine("Press any key for continuing...");
            Console.ReadKey();
        }
    }
}

第一次執行

此時,請設定可執行的 .NET Framework 專案,TypeForward,為預設起始專案,並且執行這個專案。
您會看到這個應用程式將會輸出如下的內容,我們從這個內容,可以看到,我們這裡使用的型別, Foo 是位於 MyLibAssemblyA 組件內。
TypeForward.Foo, MyLibAssemblyA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Press any key for continuing...

加入 Type Forwarding

我們準備要把 Foo 這個類別的宣告,搬移到另外一個組件 (Assembly) 中,所以,我們另外建立一個 .NET Framework 類別庫,我們命名為:MyLibAssemblyB,這個類別庫內,僅有一個類別宣告,如下所示:
namespace TypeForward
{
    public class Foo
    {

    }
}
接下來,我們回到 MyLibAssemblyA 專案內,將之前宣告 Foo 類別的 .cs 檔案,修改成為如下的程式碼。
在這裡,我們看到了,我們將類別 Foo 的宣告已經移除了 (此時,這個類別的宣告已經搬移到 MyLibAssemblyB 專案內。
並且,我們在 MyLibAssemblyA 專案內,使用屬性 (Attribute) TypeForwardedTo 來指定目的地型別 Type (Foo) 其他組件(MyLibAssemblyB)中。
最後,我們要在 MyLibAssemblyA 專案中,使用加入參考功能,將 MyLibAssemblyB 專案加入到其參考清單中。
+

現在,我們可以重新建置這個 MyLibAssemblyA 專案。
請不要去建置 .NET Framework 可執行的專案 TypeForward
using System.Runtime.CompilerServices;

[assembly: TypeForwardedTo(typeof(TypeForward.Foo))]
//namespace TypeForward
//{
//    public class Foo
//    {
//    }
//}

第二次執行 (使用 Type Forwarding)

現在,我們到 MyLibAssemblyA 專案目錄下的 TypeForward\MyLibAssemblyA\bin\Debug 內的兩個 .dll 與兩個 .pdb 檔案都複製下來。
接著,將剛剛複製下來的四個檔案,複製到 .NET Framework 可執行的專案 TypeForward 下的 TypeForward\TypeForward\bin\Debug 目錄中。
此時,請執行 TypeForward.exe 檔案,您就會看到底下輸出結果。
這個時候,我們將看到了,類別 Foo 已經從組件 MyLibAssemblyA 轉移到組件 MyLibAssemblyB 了。
TypeForward.Foo, MyLibAssemblyB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Press any key for continuing...