nuits.jp blog

C#, Xamarin, WPFを中心に書いています。Microsoft MVP for Development Technologies。

やっぱりXamarin.iOSではRealProxyは使えなかった話

動的コード生成が絡むだろうし無理だろうと思ってたんですが、なぜかRealProxyクラスはあってコンパイルはできるので試してみました。

f:id:nuitsjp:20171204133000p:plain

はい、ダメでした。bugzillaにも上がってますね。動的生成コードが多くなるからiOSじゃ無理だよと。
27847 – Linked away exception on CallContext.LogicalGetData("SomeString") on device not simulator

しかしなぜRealProxyクラスがあるんだろう?Xamarin.Macのため??良く分かりません。まぁいっか。

AOPの手段を検討してたんですが、やっぱりIL弄るしかないですかね。 全部Commandパターンにするという荒業も無い訳ではないですが、それはやりたくないのでIL操作かな。 良く分かってないので辛いなあ。

Xamarin.Forms 2.5.xで「"Xamarin.Forms.Build.Tasks.GetTasksAbi" タスクをアセンブリ~から読み込めませんでした。」というエラーが発生する場合の対処方法

とりあえずメモ程度に。

  1. Xamarin.Formsのバージョンを最新に更新する(2.5.0.77107だと無理かも知れません)
  2. ソリューションをクローズして開き直す

これでだめなら、Visual Studioを再起動しましょう。
一応私はこれでいけました。
海外のフォーラムでも同様の問題を見かけましたが、対処方法はこれ以外見当たりません。

forums.xamarin.com

技術書典3にXamarin本出展します!

来る11月22日(日)に秋葉原UDXにて技術書展3が開催されます。

techbookfest.org

今回も榎本さん率いるサークル「Xamaritans」では新刊「Extensive Xamarin」を用意してお待ちしております。 新刊の詳細情報はこちら。

https://atsushieno.github.io/xamaritans/tbf3.html

今回も私も「Plugins for Xamarin & Unit Test」という内容で寄稿させていただいています。 具体的には

  • Plugins for Xamarinの詳細な仕組みについて
  • Plugins for Xamarinを利用する場合のUnit Test戦略について

記載させていただいています。 他にも面白そうな記事が目白押しです。

残念ながら当日は家庭の事情で現地には行けませんが、興味のある方はぜひお手に取ってみていただけないでしょうか? また既刊である「Essential Xamarin」の商業誌版も当日は併売いたしますので、興味のある方はぜひお立ち寄りください!

www.amazon.co.jp

それでは(某たっきー&つばさコンビが)お待ちしております!

Xamarin.Forms 2.3.4.247で"XamlCTask task failed unexpectedly"の回避方法

Xamarin.Formsではバージョンに関係なく、次のようなケースで元々"XamlCTask task failed unexpectedly"が発生する事がありました。

  • ソリューション内のプロジェクトによってXamarin.Formsのバージョンが違う
    (よくUWPのプロジェクトだけ更新に失敗したりします)
  • Xamarin.Formsのバージョンをアップデートして、packagesフォルダに古いバージョンが残っている

これらはそれぞれ次の対策で解決する事ができまいした。

  • ソリューション内のXamarin.Formsのバージョンを統一する
  • packagesフォルダから古いXamarin.Formsのフォルダを削除する

ただ、2.3.4.247のバージョンには固有の不具合があり、これらとは別原因で"XamlCTask task failed unexpectedly"が発生する事があります。
ただし個人的な経験から再現性は100%ではなく、ただし低くもないといった感じです。

これの対策方法ですが、つぎの二つの対処方法があります。

  1. Xamarin Forms 2.3.5-pre3より新しいバージョンにアップデートする
  2. Xamarin.Forms.targetsファイルを手で修正する

つぎのXamarin.Forms 2.4から対処されるでしょうが、Previewは入れられないという人も多いでしょう。
というわけで2.の方法を記載しておきます。

まずソリューションフォルダ下のpackagesフォルダ内の次のパスを開いてください。

Xamarin.Forms.2.3.4.270\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20

開くと、つぎのようなファイルがありますが、この中のXamarin.Forms.targetsをテキストエディタで開きます。

f:id:nuitsjp:20170830091334p:plain

ファイルの末尾のほうに、つぎのような記載があります。

<Target Name="XamlC">
    <XamlCTask
        Assembly = "$(IntermediateOutputPath)$(TargetFileName)"
        ReferencePath = "@(ReferencePath)"
        Verbosity = "2"
        OptimizeIL = "true"
        DebugSymbols = "$(DebugSymbols)"
        DebugType = "$(DebugType)"/>
</Target>

ここの「DebugType = “$(DebugType)"」を削除して次のように修正します。

<Target Name="XamlC">
    <XamlCTask
        Assembly = "$(IntermediateOutputPath)$(TargetFileName)"
        ReferencePath = "@(ReferencePath)"
        Verbosity = "2"
        OptimizeIL = "true"
        DebugSymbols = "$(DebugSymbols)"/>
</Target>

これで問題なくビルドできるはずです。

元々海外のフォーラムで対策を見つけたのですが、元情報がどこだったか完全に失念したため、リンク張るのは諦めます。。。

.NET FrameworkからHttpClientを利用している.NET Standardのプロジェクトを利用する

本エントリーはこれを書いている2017.08.26時点での話ですぐ状況は変わるかもしれませんのでご注意ください。

表題の件、普通にやるとなぜかつぎのようなエラーが出ます。

System.IO.FileNotFoundException
ファイルまたはアセンブリ ‘System.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。

  • .NET Frameworkは4.7 & .NET Standard 2.0
  • .NET Frameworkは4.7 & .NET Standard 1.4
  • .NET Frameworkは4.6.2 & .NET Standard 1.4

どのパターンでもうまく動きません。 バージョンの不一致なのでしょうが、.NET 4.6.2も4.7もクラスライブラリプロジェクトを作成した直後からSystem.Net.Httpへのアセンブリ参照を持っていますが、バージョンは4.0.0.0です。

f:id:nuitsjp:20170826215713p:plain

f:id:nuitsjp:20170826215727p:plain

そして.NET Standard側は4.3.0です。

f:id:nuitsjp:20170826215819p:plain

4.0.0.0のアセンブリ参照を削除しても動作しませんし、4.1.0.0てどこからでたのやら?私にはまったく分かりませんが、とりあえず対処法はわかりました。

  1. .NET Frameworkプロジェクト作成直後にデフォルトで登録されているアセンブリ参照のSystem.Net.Httpを削除する
  2. NuGetからSystem.Net.Httpの4.3.0をインストールする

NuGet上のSystem.Net.Httpの最新は4.3.2ですが、これを入れると正しく動きませんので(.NET Standard側も4.3.2いれたら動くかも?未確認です)気を付けてください。

以上です。動いたけどいまいち釈然としませんね。。。

WPF&xUnitでテストコードからViewオブジェクトを生成する方法

例えば次のコードがあったとします。

[Fact]
public void WhenClosed()
{
    var window = new Window();
}

これを実行すると次のようなエラーがでます。

f:id:nuitsjp:20170825115056p:plain

UIはテストしないんじゃないの?と言われそうな気もしますが、Windowに貼り付ける汎用Behaviorをライブラリ化して使いまわしたいとかいう時に、Windowインスタンスが作れないがためにUnitTest書けないじゃんてな事が、稀に良くあります。

WPFなどはUI層はSingle Thread Apartment(STA)なスレッド上で実行される必要があります(この表現はもしかしたら正しくないかもしれません)。
よくUIはUIスレッドで実行しろと言われるあれです。

xUnitはマルチスレッドでテスト実行されますし、STAではもちろんありません。どうしましょう?こまったな。
と思っていたら、神がいました。

www.nuget.org

このパッケージをインストールして次のようにコードを修正します。

[WpfFact]
public void WhenClosed()
{
    var window = new Window();
}

FactAttributeからWpfFactAttributeに変更するだけでちゃんとSTAで動作させてくれます。凄い!どうなってるの!?

という訳で、今日はこれだけ。
いやあ、自力で何とかしようとしかけて、しないで済んで助かったなあ。