Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
本日のサンプルコードは後日公開します作業手順も暗記する必要はありません
ちょっと分量多めなので、少し(?)早口です
-クロスデバイス開発の必要性
iOS WinRTAndroid
Objective-C
Storyboard
Java
AXML
C#/VB
XAML
iOS ライブラリ .NET BCLAndroid ライブラリ
iOS Native API WinRT Native APIAndroid Native API
異なる言語 異なる
ツール
-Xamarin & Xamarin.Forms による解決
iOS WinRTAndroid
C#
Storyboard
C#
AXML
C#/VB
XAML
Xamarin.Forms
Portable Class Library(または Shared Asset Project)
C# で記述可能!
C#XAML
共有可能!
共有可能!
-Xamarin.Forms の向き・不向き
Xamarin.Forms が得意なアプリ Xamarin.Forms が苦手なアプリ
• アニメーションを多用• 複雑な UI 操作が必要• プラットフォーム固有処理が大量に必要
• 比較的シンプルな UI
• データ参照・更新が主体• プラットフォーム固有処理が比較的少ない
-具体例)データバインドアプリケーション
iPhone 6 (実機)
Nexus 7 2013 (実機)
iPad 2 (実機)
シングルコードマルチデバイス
-Hello World, Xamarin.Forms !
Hello World, Xamarin.Forms !
-Hello World, Xamarin.Forms !
PCL タイプの Xamarin.Forms プロジェクトを作成※手作業でソリューションファイルを組み立てることも可能
業務構造を意識した形で XAML ファイルを追加
ブートストラップコードが含まれるプロジェクト
Xamarin.Forms を利用する共有 PCL プロジェクト
-Hello World, Xamarin.Forms !
HelloWorldPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Decode2015.MainPage"Title="メインメニュー">
<StackLayout><Button x:Name="btnBizA" Text="Hello World サンプル" />
</StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Decode2015.BizA.HelloWorldPage"
Title="Hello World">
<StackLayout>
<Entry x:Name="entName" Text="Nobuyuki" /><Button x:Name="btnGetMessage" Text="メッセージ取得" />
<Label x:Name="lblMessage" />
</StackLayout>
</ContentPage>
MainPage.xaml
-Hello World, Xamarin.Forms !
public HelloWorldPage()
{
InitializeComponent();
btnGetMessage.Clicked += btnGetMessage_Clicked;
}
void btnGetMessage_Clicked(object sender, EventArgs e)
{
lblMessage.Text = "Hello World, " + entName.Text;
}
HelloWorldPage.xaml.cs
public MainPage()
{
InitializeComponent();
btnBizA.Clicked += btnBizA_Clicked;
}
void btnBizA_Clicked(object sender, EventArgs e)
{
Navigation.PushAsync(new BizA.HelloWorldPage());
}
MainPage.xaml.cs
-Hello World, Xamarin.Forms !
public class App : Application
{
public App()
{
this.MainPage = new NavigationPage(new MainPage());
}
}
C#
NavigationPage でページをラップすると...
ヘッダーが付与されるようになり、iOS でも前画面に戻れるようになる
-Hello World, Xamarin.Forms !
開発機 Macintosh
Xamarin.iOS
Build Host iOS シミュレータVisual Studio iOS 実機
配置と実行
Android 実機Android
エミュレータ
仮想化環境
-デバイスによる実行結果の差異について
-デバイスによる実行結果の差異について
XAML
<Label><Label.Text>
<OnPlatform x:TypeArguments="x:String" iOS="Hello World, iOS" Android="Hello World, Android" WinPhone="Hello World, WinPhone" />
</Label.Text></Label>
// 値を変えたい場合lblMessage.Text = Device.OnPlatform<string>(
"iOS", "Android", "WinPhone");
// 処理を分けたい場合Device.OnPlatform(
() => { lblMessage.Text = "iOS"; },() => { lblMessage.Text = "Android"; },() => { lblMessage.Text = "WinPhone"; }
);
C#① OnPlatform 属性の利用 ② Device.OnPlatform メソッドの利用
-WinRT XAML と Xamarin.Forms XAML の類似点と相違点
【主な類似点】
• XAML の基本的な構文• リソースデータの扱い• スタイルの考え方• データバインドの考え方• 主要なレイアウト部品や
UI 部品
【主な相違点】
• UI 部品やレイアウト部品の名前
• 主要プロパティの名前• 任意のコンテンツ合成や高度な UI 指定ができない
-Xamarin.Forms でどこまでの UI が開発できるのか?
-Xamarin.Forms アプリからのサーバ連携
Web サーバ各種の
DB サーバ
既存の各システム
XML 形式などのデータ
業務データ
Xamarin.Formsアプリケーション 開発!
-PCL におけるサービス参照について
• PCL プロジェクトでもサービス参照の機能は利用できるように見えるが...
• 実際に作成してみると、Android,
iOS では残念ながら動作しない
-スクラッチでのリモート通信開発
Web サーバ DB サーバ業務データ
クライアント
ツールベースの開発
通信手法
サービス参照(プロキシクラス)
SOAPWCF
(または *.asmx)
スクラッチでの開発 HttpClientXML または
JSONASP.NET Web API
こちらを利用!
-HttpClient + Web API + EF によるサーバアプリ開発
Web サーバ
pubsデータベース
Xamarin.Formsアプリケーション
データ転送オブジェクト(AuthorDTO)
Web API コントローラ(ListAuthors
WebApiController)
O/R マッパー(Pubs.dbml)
(ListAuthorsPage.xaml)
HttpClient
-HttpClient + Web API + EF によるサーバアプリ開発
• データ転送用の POCO (DTO) を別建てで PCL として定義
• サーバとクライアントの両方から参照設定して共有するWeb サーバ DB サーバ
業務データクライアント データ転送オブジェクト
iOS
Android
Xamarin
.FormsDTO
ASP.NET
Web API参照! 参照!
-HttpClient + Web API + EF によるサーバアプリ開発
開発機 Macintosh
Xamarin.iOS
Build Host シミュレータVisual Studio 実機
配置と実行
IIS Express 実機エミュレータ
仮想化環境
開発用 Web サーバ
エミュレータ/シミュレータ/実機いずれからもアクセスできない!
Azure Web サイト開発用 Web サーバやAzure Web サイトを使い、開発とテストを行う
HttpClient + Web API + EF によるサーバアプリ開発
-HttpClient + Web API + EF によるサーバアプリ開発
-HttpClient + Web API + EF によるサーバアプリ開発
public MainPage()
{
InitializeComponent();
btnBizA.Clicked += btnBizA_Clicked;
btnBizB.Clicked += btnBizB_Clicked;
}
void btnBizB_Clicked(object sender, EventArgs e)
{
Navigation.PushAsync(new BizB.ListAuthorsPage());
}
C#
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Decode2015.MainPage"Title="メインメニュー">
<StackLayout><Button x:Name="btnBizA" Text="Hello World サンプル" />
<Button x:Name="btnBizB" Text="著者データ参照" />
</StackLayout>
</ContentPage>
MainPage.xaml
-HttpClient + Web API + EF によるサーバアプリ開発
-HttpClient + Web API + EF によるサーバアプリ開発
[DataContract]
public class AuthorDTO
{
[DataMember]
public string AuthorId { get; set; }
[DataMember]
public string AuthorName { get; set; }
}
C#
-HttpClient + Web API + EF によるサーバアプリ開発
[Route("BizB/ListAuthors/{action}")]
public class ListAuthorsWebApiController : ApiController
{
[HttpGet]
public List<AuthorDTO> GetAllAuthors()
{
... (完全なソースコードは次ページ参照)}
}
C#
重要!
[Route("BizB/ListAuthors/{action}")]
public class ListAuthorsWebApiController : ApiController
{
[HttpGet]
public List<AuthorDTO> GetAllAuthors()
{
using (pubsEntities pubs = new pubsEntities())
{
var query = from a in pubs.authors
select new AuthorDTO
{
AuthorId = a.au_id,
AuthorName = a.au_fname + " " + a.au_lname
};
return query.ToList();
}
}
}
C#
-HttpClient + Web API + EF によるサーバアプリ開発
-HttpClient + Web API + EF によるサーバアプリ開発
XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"x:Class="Decode2015.BizB.ListAuthorsPage" Title="著者データ参照">
<StackLayout>
<ListView x:Name="lvwAuthors" RowHeight="60" VerticalOptions="FillAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Vertical" Padding="0,6,0,0">
<Label Text="{Binding AuthorId}" FontAttributes="Bold" FontSize="18" />
<Label Text="{Binding AuthorName}" FontSize="18" LineBreakMode="TailTruncation" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView><Button x:Name="btnGetAllAuthors" Text="データ取得" />
</StackLayout>
</ContentPage>
-HttpClient + Web API + EF によるサーバアプリ開発
public ListAuthorsPage()
{
InitializeComponent();
btnGetAllAuthors.Clicked += btnGetAllAuthors_Clicked;
}
async void btnGetAllAuthors_Clicked(object sender, EventArgs e)
{
string apiUrl = "http://decode2015webapi.azurewebsites.net/BizB/ListAuthors/GetAllAuthors";
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
string responseString = await response.Content.ReadAsStringAsync();
List<AuthorDTO> results = JsonDeserialize<List<AuthorDTO>>(responseString);
lvwAuthors.ItemsSource = results;
}
C#
-HttpClient + Web API + EF によるサーバアプリ開発
public static T JsonDeserialize<T>(string stringToDeserialize)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
byte[] bytes = Encoding.UTF8.GetBytes(stringToDeserialize);
MemoryStream ms = new MemoryStream(bytes);
return (T)serializer.ReadObject(ms);
}
C#
-HttpClient + Web API + EF によるサーバアプリ開発
-アプリケーションアーキテクチャ上のポイント
-1. RESTful 型設計 vs RPC 型設計
商品発注サービス
カタログ管理サービス
注文伝票
注文結果伝票
サービス呼び出し
商品
口コミ
GET
PUT
DELETE
GET
PUT
DELETE
CRUD 処理RESTful 設計 RPC スタイル設計
業務アプリではこちらの方が設計しやすい
-1. RESTful 型設計 vs RPC 型設計
public class AuthorsController : ApiController
{
public List<Author> Get() { ... }
public Author Get(string authorId) { ... }
public void Put(Author authorToUpdate) { ... }
public void Post(Author authorToInsert) { ... }
public void Delete(string authorId) { ... }
}
C#
HTTP Verb 意味
GET READ
POST CREATE
PUT UPDATE
DELETE DELETE
-1. RESTful 型設計 vs RPC 型設計
-2. JSON vs XML
{"result":"Hello World Nobuyuki"}
簡単なデータならよいが、日付型や byte[] 型などの扱いは面倒
-2. JSON vs XML
string apiUrl = "http://decode2015webapi.azurewebsites.net/BizB/ListAuthors/GetAllAuthors";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("text/xml"));
HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
string responseString = await response.Content.ReadAsStringAsync();
C#
-WCF vs ASP.NET Web API
WCF ASP.NET Web API
API 設計スタイル RPC 型のみ自由(RPC 型、RESTful 型など)
メッセージフォーマット SOAP のみ
自由(XML、JSON など)
通信プロトコル自由(HTTP、TCP/IP など)
HTTP のみ
-WCF vs ASP.NET Web API
Web サーバ DB サーバ業務データ
クライアント
ツールベースの開発
通信手法
サービス参照(プロキシクラス)
SOAPWCF
(または *.asmx)
スクラッチでの開発 HttpClientXML または
JSONASP.NET Web API
要設計
-ASP.NET Web API + EF で開発する場合のテクニック
本日のランチセッションにて開催!
1. WinRT と Xamarin.Forms XAML の主な相違点2. ASP.NET Web API + EF の開発テクニック
-レイアウト部品の名称の違い
Xamarin.Forms WinRT
積み重ね StackLayout StackPanel
絶対座標 AbsoluteLayout Canvas
格子状 GridLayout Grid
相対座標 RelativeLayout (なし)
スクロール ScrollView ScrollViewer
枠線 Frame Border
サイズフィット (なし) Viewbox
-StackLayout の活用テクニック
Xamarin.Forms XAML
<ContentPage ...><StackLayout><Frame OutlineColor="Accent"> ... </Frame><ScrollView Orientation="Vertical" VerticalOptions="FillAndExpand"><StackLayout>... (表示する内容) ...
</StackLayout></ScrollView><Button x:Name="btnUpdate" Text="更新" BorderWidth="2" /><Button x:Name="btnGoBack" Text="前の画面に戻る" BorderWidth="2" />
</StackLayout></ContentPage>
FillAndExpand
余白いっぱいに引き伸ばす
-UI 部品の名前の違い
Xamarin.Forms WinRT の場合は...
ActivityIndicator ProgressRing
BoxView Rectangle
Button Button
DatePicker DatePicker
Editor TextBox
Entry TextBox
Image Image
Label TextBlock
ListView ListView
Xamarin.Forms WinRT の場合は...
Map BingMaps
Picker ComboBox
ProgressBar ProgressBar
Slider Slider
Switch ToggleButton
TimePicker TimePicker
WebView WebView
- CheckBox
- GridView
-主要プロパティの名前の違い
WinRT Xamarin.Forms
余白制御 Margin Padding
位置制御 VerticalAlignment/HorizontalAlignment VerticalOptions/HorizontalOptions
前景色 Foreground TextColor など
背景色 Background BackgroundColor/BackgroundImage など
データバインド DataContext BindingContext
-データアノテーションを利用した単体入力エラーチェック
[DataContract]
public class FindAuthorRequestDTO
{
[DataMember]
[Required]
[RegularExpression(@"^[0-9]{3}-[0-9]{2}-[0-
9]{4}$")]
public string AuthorId { get; set; }
}
C#
[HttpPost]
public AuthorDetailDTO
FindAuthor(FindAuthorRequestDTO request)
{
if (ModelState.IsValid == false) throw new
HttpResponseException(HttpStatusCode.BadRe
quest);
....
}
C#
-EF エンティティデータモデルのシリアル化
-EF エンティティデータモデルのシリアル化
public string Property(EdmProperty edmProperty){
return string.Format(..., "[System.Runtime.Serialization.DataMember]¥r¥n{0} {1} {2} {{ {3}get; {4}set; }}",...);
}
public string NavigationProperty(NavigationProperty navProp){
...return string.Format( ..,
"[System.Runtime.Serialization.DataMember]¥r¥n{0} {1} {2} {{ {3}get; {4}set; }}", ...);}
public string EntityClassOpening(EntityType entity){
return string.Format(...,"[System.Runtime.Serialization.DataContract(IsReference = true)]¥r¥n {0} {1}partial class {2}{3}", ...);
}
Pubs.tt
i.
ii.
iii.
-3 種類の POCO オブジェクトの使い分け
DAC
データベース
*.edmx
SI + BC
ASP.NET Web API
API Controller
POCO
(エンティティ)
BEC
ADO.NET
Entity Framework
POCO
(DTO)
BEC
SA
HttpClient
BC
サーバ呼び出しロジック
Xamarin
.Forms
*.xaml
*.xaml.cs
コードビハインド
POCO
(ViewModel)
UI
-3 種類の POCO オブジェクトの使い分け
ViewModel DTO エンティティモデル
内容 • 双方向データバインドの実装に利用する • データの転送に利用する• 上り電文と下り電文とで別の DTO が利用される
• Entity Framework によるデータベースからのデータ取得に利用する
特徴 • UI に併せて最適化されて定義される• 入力で期待するデータの型と、POCO 上に定義されるデータ型がずれることがある
• データ入力チェックのために、データアノテーションが利用される
• エラー検証などのために、特定の基底クラスから派生して作られることが多い
• シリアル化のために、[DataContract] 属性が利用される
• サーバ側でのデータ入力チェックのために、データアノテーションが利用される
• データベース構造に併せて定義される• 遅延ローディング機能などを有効にするために、多くのプロパティが virtual 定義されている
• EF から読み取ったデータはそのままではシリアル化できない
• データベースからリバースして作った場合には、データアノテーション定義がない
データ構造 UI に最適化 通信に最適化 DB 構造に最適化
データアノテーション
○ (UIに最適化) ○ (上り電文のみ) △ (DB構造に最適化)
シリアル化 × (不要なことが多い) ○ (必須) × (既定ではシリアル化不可)
-3 種類の POCO オブジェクトの使い分け