Movatterモバイル変換


[0]ホーム

URL:


Zenn
とりえとりえ

【Xamarin.Mac】プロジェクト内のリソースファイルを実行時にアプリから読み込む

に公開
2021/03/04

やりたいこと

Xamarin.Macで作ったデスクトップアプリで、プロジェクト内に用意した設定やテンプレートなどのファイルを実行時に読み込ませたい。

背景・利用シーン

Xamarin.Macでlog4netを使うため、起動時にXMLで書かれたファイルを読みこんでlog4netに渡したい。
また、アプリに簡易的なWebサーバを持たせたい時にテンプレートをファイルを読み込みたいという場面があり、その際にも同様の方法で実現した。

手順

今回はファイルを読み込む例としてプロジェクト内のJSONファイルを読み込み、前回作成した表に表示することにする。
前回の記事:DelegateとDataSourceを使ったTableViewにインクリメンタルサーチを実装する

ファイルの追加

読み込むJSONファイルを作成する。
プロジェクト下にResourcesというフォルダがあるのでここにファイルを追加する。ファイル名はmembers.jsonとした。

members.json

{"members":[{"Name":"a2see","TwitterId":"a2see"},{"Name":"うぇるち","TwitterId":"welchi_"},{"Name":"想間ミレイ","TwitterId":"zerovabi"},{"Name":"月見ねぎとろ","TwitterId":"tukimi_negitoro"},{"Name":"創好リナ","TwitterId":"TsukusuLina"},{"Name":"でんじぃ","TwitterId":"den_oldman"},{"Name":"とりえ","TwitterId":"trpla226"},{"Name":"なもなき","TwitterId":"nam0naki"}]}

ビルドアクションの設定

ソリューションウィンドウからmembers.jsonファイルのコンテキストメニューを表示し、「プロパティ」をクリックする。

ビルド > ビルドアクションドロップダウンで「EmbeddedResource」を選択する。
EmbeddedResourceを選ぶと、「リソースID」にデフォルトのものが設定される。これをクリップボードにコピーしておく。
今回は「tablesearch.Resources.members.json」というIDになった。

ファイルを読み込みの処理を記述する

今回はViewControllerの生成時にファイルを読みこむようにする。
Assembly#GetManifestResourceStream()にリソースIDを渡すことで、Streamとして取得することができる。
あとはStreamを文字列として読み込み、欲しい形に変換して前回作った表示処理に食わせる。

なお、JSONのパースのにあたってNugetでNewtonsoft.Jsonを導入した。

ViewController.cs(該当部分)

// Resource内のファイルを取得var assm= Assembly.GetExecutingAssembly();var membersStream= assm.GetManifestResourceStream("tablesearch.Resources.members.json");// string型としてファイルの最後まで読み込むvar membersJson=newStreamReader(membersStream).ReadToEnd();// 取得したJSONをList<Member>に変換var membersJObj= JObject.Parse(membersJson);var membersJArray=(JArray)membersJObj["members"];Members= membersJArray.Select(jt=> jt.ToObject<Member>()).ToList().AsReadOnly();

JSONファイルの内容をテーブルに表示することができた。

環境

Mac OS X 10.15.6
Visual Studio for Mac Community 8.8.1(build 37)
Xamarin Mac 7.0.0.15
XCode Version 12.2

付録

前回のコードに変更を加えて作成した今回のViewController.csファイルの全容を公開しておく。

ViewController.cs

usingSystem;usingSystem.Collections.Generic;usingSystem.IO;usingSystem.Linq;usingSystem.Reflection;usingAppKit;usingFoundation;usingNewtonsoft.Json.Linq;namespacetablesearch{publicpartialclassViewController:NSViewController{readonlyMemberTableViewDataSource dataSource=newMemberTableViewDataSource();IReadOnlyCollection<Member> Members;publicViewController(IntPtr handle):base(handle){// Resource内のファイルを取得var assm= Assembly.GetExecutingAssembly();var membersStream= assm.GetManifestResourceStream("tablesearch.Resources.members.json");// string型としてファイルの最後まで読み込むvar membersJson=newStreamReader(membersStream).ReadToEnd();// 取得したJSONをList<Member>に変換var membersJObj= JObject.Parse(membersJson);var membersJArray=(JArray)membersJObj["members"];            Members= membersJArray.ToList().Select(jt=> jt.ToObject<Member>()).ToList().AsReadOnly();            dataSource.Members=newList<Member>(Members);}publicoverridevoidViewDidLoad(){base.ViewDidLoad();            MemberTableView.DataSource= dataSource;            MemberTableView.Delegate=newMemberTableViewDelegate(dataSource);}publicoverrideNSObject RepresentedObject{get{returnbase.RepresentedObject;}set{base.RepresentedObject=value;// Update the view, if already loaded.}}partialvoidKeywordChanged(NSObject sender){var keyword=((NSSearchField)sender).StringValue;            dataSource.Members= Members.Where(member=> member.Name.Contains(keyword)).ToList();            MemberTableView.ReloadData();}}publicclassMemberTableViewDataSource:NSTableViewDataSource{publicList<Member> Members{get;set;}=newList<Member>();publicoverridenintGetRowCount(NSTableView tableView){return Members.Count;}}publicclassMemberTableViewDelegate:NSTableViewDelegate{privateconststring CellIdentifier="MemberCell";privateMemberTableViewDataSource dataSource;publicMemberTableViewDelegate(MemberTableViewDataSource dataSource){this.dataSource= dataSource;}publicoverrideNSViewGetViewForItem(NSTableView tableView,NSTableColumn tableColumn,nint row){NSTextField view=(NSTextField)tableView.MakeView(CellIdentifier,this);if(view==null){                view=newNSTextField();                view.Identifier= CellIdentifier;                view.BackgroundColor= NSColor.Clear;                view.Bordered=false;                view.Editable=false;                view.Selectable=false;}var member= dataSource.Members[(int)row];switch(tableColumn.Title){case"Name":                    view.StringValue= member.Name;break;case"Twitter ID":                    view.StringValue= member.TwitterId;break;}return view;}}}

また、Newtonsoft.Jsonでデシリアライズするに当たってMemberクラスの定義も変更したので、変更後のコードを以下に掲載する。

Member.cs

namespacetablesearch{publicclassMember{publicstring Name;publicstring TwitterId;publicMember(string name,string twitterId){            Name= name;            TwitterId= twitterId;}}}
とりえ

VRChat関連でUnityをやったり、.Net Frameworkでデスクトップアプリを開発したりしてます。つまりC#メイン。JavaやJavaScriptやPHPなども多少経験あります。

バッジを贈って著者を応援しよう

バッジを受け取った著者にはZennから現金やAmazonギフトカードが還元されます。

VRChat関連でUnityをやったり、.Net Frameworkでデスクトップアプリを開発したりしてます。つまりC#メイン。JavaやJavaScriptやPHPなども多少経験あります。


[8]ページ先頭

©2009-2025 Movatter.jp