All posts by Ishisaka

Forza Horizon 4 ロック車のリスト #ForzaHorizon4

Forza Horizon 4/Cars | Forza Motorsport Wiki | FANDOM powered by Wikia

最終更新: 2019/08/13

Forza Editionはこちら: Forza Horizon 4 Forza Edition リスト #ForzaHorzion4

レベルアップにより解除される車

  • 2013 Ariel Atom 500 V8 – Speed Zone Hero level 11
  • 2005 BMW M3 – Drift Run level 8
  • 1985 Chevrolet Monte Carlo Super Sport – LaRacer @ Horizon level 10
  • 2018 Dodge Challenger SRT Demon – The Stunt Driver level 10
  • 1969 Ford Mustang Boss 302 – Drift Club level 10
  • 1985 Ford RS200 – Dirt Racing Series level 4
  • 1991 Hoonigan Rauh-Welt Begriff Porsche 911 Turbo – Street Scene level 17
  • 2015 Jaguar XKR-S GT – Road Racing Series level 16
  • 2018 Jeep Grand Cherokee Trackhawk – Cross Country Series level 8
  • 2016 Jeep Trailcat – Cross Country Series level 4
  • 2014 Lamborghini Huracán LP 610-4 – Road Racing Series level 4
  • 2002 Nissan Skyline GT-R V-Spec II – Street Scene level 4
  • 2010 Noble M600 – Speed Trap Hero level 11
  • 2011 Penhall The Cholla – Cross Country Series level 14
  • 2015 Porsche Cayman GTS – Road Racing Series level 8
  • 2017 Ram 2500 Power Wagon – Dirt Racing Series level 8
  • 1973 Renault Alpine A110 1600s – Dirt Racing Series level 16
  • 1993 Renault Clio Williams – Street Scene level 8
  • 2015 Ultima Evolution Coupe 1020 – The Drag Strip level 4
  • 2016 Zenvo ST1 – World’s Fastest level 10
  • 2014 Mercedes-Benz G 63 6X6 – Top Gear level 7
  • 2018 Top Gear Track-tor – Top Gear level 5
  • 2017 Mercedes-Benz E350D 4MATIC All-terrain “Project E-AT” – Top Gear level 4

Continue reading Forza Horizon 4 ロック車のリスト #ForzaHorizon4

Forza Horizon 4の既知の問題 #ForzaHorizon4

最終更新: 2019-06-09

情報源:FH4 Known Issues – Forza Support

シリーズ2

スターカード

新しいスターカード機能で発生するいくつかの問題を認識しています。

  • いくつかの統計は、要求された目標に達したかまたはそれを超えたにもかかわらず、完了として表示されないかもしれません。ゲームを再起動するとこの問題は解決します。
  • プレイヤーが本土とフォーチュン島の両方ですべての道路を発見した場合、道路統計は誤った合計道路数を表示します。これはまもなく新しいアップデートで対処されます。
  • ショーケースが勝ち、Showcase Remixesが勝ちとなった場合、全プレイヤーが0と表示されます。これは、統計が以前に正しく追跡されていなかったためです。これを修正する方法はありません。プレイヤーはこれらのイベントを再レースしてこれらの統計を増やし、これらのカテゴリーを完成させる必要があります。
  • 事業収入の統計情報もこれに当てはまります。このアップデート以降の累積されます
  • シーズンイベントとシーズンチャンピオンシップ統計情報は、フェスティバルパスがライブになったシリーズ6アップデート(2/6)以降の記録のみ加算されます。
  • 1対1レースのカウントはFortune Island拡張が追加(12/3)以降の統計が利用されます。

クロスプラットフォーム

  • リプレイモードで、ギア変化があってもエンジン音が変わりません。(恐らくScorpio(Xbox One X) 60FPSの場合のみ)
  • 通知をオフにしていると、トレジャーハント(宝物探し)の場所が出現しません。トレジャーハントの場所が出現するように通知はONにしてください
  • ガレージに表示されない車が、オートショーでは「所有」と表示される。
  • Lake Lodge Houseの所有権狩りセットされる。
  • Cinematicの時を除いてオーディオロス。
  • クラブに参加したり、クラブを設立出来ない。
  • 前のシリーズ同シーズンで既に同じシーズンイベントをクリアしていた場合に、クリアしていると表示される場合がある。
  • プログレッションバーがレベルアップ後も消えない
  • いくつかのストーリー達成実績が誤って達成となっている。

XBoxでの既知の問題

  • Xbox One – オーディオ – タイトル全体で発生するオーディオヒッチがあります。これらは非常に短い期間無音になります。
  • ディスクからのインストール後にリージョンと言語が変更された場合、ゲームを再インストールする必要があります。
  • インストール中にゲームをプレイすると、パフォーマンス上の問題が発生することがあります。
  • 以前のフォルツァのタイトルから大量に保存されたゲームデータを同期するとき、プロファイルの同期時間が過度にかかります。

PC版での既知の問題

  • ドライブラインといくつかの照明/ブルーム効果がちらつくことがあります。 Windows 10バージョン1809または1803を使用している場合は、この問題を解決するために NVIDIA hotfix 430.97 をインストールしてください。
  • Nvidiaコントロールパネルからの強制異方性フィルタリング設定を設定すると、地形がぼやけて見えます。
  • ゲームプレイ中にイヤホンがサス混まれると、Realtek HDオーディオマネージャーはゲームのサウンドを切断します。
  • トレンドマイクロ、マキシマムセキュリティ、コモドアンチウィルス、ソフォス、Emisoft、Avira灘のアンチウィルスソフトウェアがインストールされていると、ゲームが起動出来ないことがあります。
  • 起動時にヘッドフォンを取り外すと、音声が失われ不安定になります。
  • FH4がバックグラウンドアプリケーションであることを無効にされていると、一時停止および再開時にクラッシュまたはハングする可能性があります。
  • デフォルトの再生が24bit 44100Hzに設定されている場合のオーディオの破損(他の利用可能な設定では起こりません)。
  • プレーヤーが[サウンドオプション]> [スピーカーのプロパティ]> [空間]の[すべての効果音を無効にする](または同様の)のチェックマークを付けた場合、または[空間サウンドフォーマット]を[なし]に設定した場合は、ゲームが停止します。
  • マウスとキーボード – カスタムキーボードプロファイルを設定するときに、特定のキーバインドグループの1つを変更すると、そのグループ内のすべてのアクションがバインド解除されます。
  • ドライババージョン411.63を使用する場合のNVIDIA GTX 780およびGTX 780 TIのハードロック。399.24にロールバックすると問題は解決します。
  • スピードゾーンにぶつかるとクラッシュする。Windowsバージョン1809にロールバックしてください。

ホイールの既知の問題

  • Fanatec Clubsport V2 – ホイールがGIPモードのとき、ホイールFFBは初期化されません。*回避策は、PC上でXboxモードでホイールを動かさないことです。
  • Mad Catz Pro – Alt + Tabキーを押すか最小化すると、力のフィードバックと振動が失われる。
  • パッドでタイトルを起動してからホイールをオンにすると、パッド設定が適用されます。ホイールだけでゲームを始めてください

Excel-DNA

Excel-DNAとは

Excel-DNA

Excel-DNAはC#やF#, VBのような.NET Frameworkを使って、xll形式のExcel拡張を作成するためのライブラリ、ツールです。CodePlex上で開発が行われています。ライセンスはオリジナルの物ですので、CodePlexのサイトで確認ください。

xllは基本的にC/C++用のExcel APIを使用したExcelの拡張ライブラリですが、非常に薄いネイティブのラッパを通すことで、高速にExcelから.NETのクラスライブラリを呼び出します。

特に、Excelのユーザー定義関数の作成を.NETの言語で行いたいような場合に非常に強力なツールです。今までの良くあるやり方は、.NETの言語でActiveX DLLを作ってExcelのオートメーションアドインとしてUDFを提供する方式ですが、.NETでActiveX DLLを作るためのお約束が非常に多く、コードも煩雑だし、間にCCWもはいるしなので、あまり見やすい物でも作りやすい物でもありませんでしたが、このExcel-DNAでは最低限のコードで、Excelのユーザー定義関数の開発が行えます。

作業の流れ

Visual Studioで、Excelのユーザー定義関数を開発する場合には以下の手順で、作業を行います。

先ず、クラスライブラリのプロジェクトを作成します。

SnapCrab_新しいプロジェクト_2014-6-27_23-0-32_No-00

プロジェクトが決まったら、NugetでExcel-DNAを追加します。Guiを使う場合にはExcel.DNAで検索をして、下の図のようにExcel-DNAを選択して追加します。

SnapCrab_MyExcelDnaSample1 - NuGet パッケージの管理_2014-6-27_23-2-16_No-00

手動でライブラリの参照を追加した場合には、dllの他にプロジェクトに.dnaというXMLの動作定義ファイルを追加しないといけないのですが、Nugetでのライブラリ追加時にいかのようなそのまま使用できる.dnaファイルが追加されます。


  
  
  

ライブラリをNugetで追加したら、以下のようにC#のコードで実際のExcel関数を追加します。このとき、クラスとExcel関数となるメソッドはStaticで記述します。

namespace MyExcelDnaSample1
{
    using ExcelDna.Integration;

    /// 
    /// Excel DNAを使用してExcelのユーザー定義関数(UDF)を作成するサンプル
    /// UDFはstaticなクラスにstaticなメソッドとして記述する。
    /// 
    public static class MyExcelDnaSample1
    {
        /// 
        /// 引数の名前にHelloを言う
        /// 
        /// あいさつの相手
        /// あいさつ
        [ExcelFunction(Description = "引数にHelloを言う。", Category = "Tadahiro Lib.")]
        public static string SayHello(string name)
        {
            return "Hello " + name;
        }
    }
}

3行目で、Excel.Dnaへの参照を追加しています。
12行目のExcelFunctionよいうAttributeはなくてもPublicでStaticなメソッドはExcelはユーザー定義関数と認識しますが、このAttributeを使って説明とカテゴリを設定しておけば、Excelの関数のウイザードでそれらが表示されます。

これをビルドしてみましょう。以下がビルド結果です。

1>------ ビルド開始: プロジェクト:MyExcelDnaSample1, 構成:Debug Any CPU ------
1>  MyExcelDnaSample1 -> d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll
1>  D:\documents\visual studio 2013\Projects\MyExcelDnaSample1\packages\Excel-DNA.0.32.0\tools\ExcelDna.xll
1>  1 個のファイルをコピーしました
1>  D:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.dna
1>  1 個のファイルをコピーしました
1>  D:\documents\visual studio 2013\Projects\MyExcelDnaSample1\packages\Excel-DNA.0.32.0\tools\ExcelDna64.xll
1>  共有違反です
1>  0 個のファイルをコピーしました
1>  Using base add-in d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.xll
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: 60383
1>    ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll.
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: 1571
1>    ->  Updating resource: Type: DNA, Name: __MAIN__, Length: 433
1>  Completed Packing d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn-packed.xll.
1>  Using base add-in d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64.xll
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: 60383
1>    ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll.
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: 1571
1>    ->  Updating resource: Type: DNA, Name: __MAIN__, Length: 433
1>  Completed Packing d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64-packed.xll.
========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========

手でExcel-DNAのライブラリを参照追加した場合、最終的なxllとする作業は手作業になってしまうのですが、NuGetでライブラリ追加した場合はプロジェクトのビルド時にPowerShellスクリプトが呼び出されてパッケージ化の作業まで実行してくれます。

ビルドが成功したら、ターゲット先のフォルダを開いて、.xllをダブルクリックするか、Excelを起動してドラッグ&ドロップしてください。.xllはExcelのプロセッサアーキテクチャにあわせた方を選択してください。

SnapCrab_Debug_2014-6-27_23-7-14_No-00

以下のようなダイアログが表示される場合には、左側のこのアドインをこのセッションに限り有効とするをクリックします。

SnapCrab_Microsoft Excel のセキュリティに関する通知_2014-6-27_23-7-34_No-00

Excelが起動したらCtrl + Nで新規のワークブックを開きます。

適当なセルで=をおしてSayHello(“Tadahiro”)と入力すれば、自分がC#で作成したユーザー定義関数が動作することを確認できると思います。

SnapCrab_Book1 - Excel_2014-6-28_0-7-6_No-00_01

SnapCrab_NoName_2014-6-28_0-10-15_No-00

関数の挿入ボタンを押して、ウインドウを表示させると、先ほどExcelFunctionで設定したDescriptionの内容が表示されています。

SnapCrab_NoName_2014-6-28_0-12-21_No-00

何もないセルで関数の挿入を選択すると、以下のようにExcelFunctionで設定されたカテゴリを確認することが出来ます。ちなみにカテゴリを設定しなかった場合には、xllの名前がカテゴリになります。

SnapCrab_関数の挿入_2014-6-28_0-13-45_No-00

まとめ

  • Excel-DNAは.NET FrameworkでExcel拡張を作成するための、ライブラリ、ツール。
  • Excel-DNAを使用すると非常に少ない労力でExcelユーザー定義関数の開発が行え、関数自体の実装に集中できる。
  • Automationアドインでは無く、xllとして実装される。
  • Nugetを使用するともっと労力を減らせる。

また、CodePlexのサイトからZIPをダウンロードすることもあわせてお勧めします。豊富なサンプルがありますので、参考になると思います。

Visual Studio Tools for Officeで何故かユーザー定義関数の開発がサポートされていないとか、そもそもいけていないとか、Automationアドインの開発の煩雑さに辟易とか、既存の.NEtでのExcel拡張の開発に嫌気がさしたそういうみなさんは、一度Excel限定ではありますが、Excel-DNAを試してみてはいかがでしょう。

今回のコードは以下を参照。

https://github.com/ishisaka/ExcelDnaSample1

ASP.NET Web APIサーバー編

以前WCF Web APIについて書きましたが、その後紆余曲折あり、まず、WCFのプロダクトでは無くなり、それに従いWCFとしてホストされることは出来なくなり、ASP.NET MVCによるホスト機能に特化され、名前もASP.NET Web APIとなり、実質的にASP.NET MVC 4の1機能になっています。

また、新たに公開されたVisual Studio 2012ではASP.NET 4 Webアプリケーションテンプレートでサポートされています。

※以下記事の元になった記事は日本マイクソフト井上さんの記事(Web APIをはじめてみよう)が元になっています

そこで、以前の記事でWCF Web APIで書かれた内容をASP.NET Web APIで書き直したいと思います。

準備

ASP.NET 4 Webアプリケーションテンプレートを使って新しいプロジェクトを作成します。下の図と異なりますが、ソリューション名はSuperHero2とします。

新しいASP.NET MVC 4プロジェクトダイアログでWeb APIを選択します。

OKをクリックすると、基本のものに加えてWeb API関連のコンポーネントへの参照やファイルが追加されたASP.NET MVC 4のプロジェクトが作成されます。 Continue reading ASP.NET Web APIサーバー編

WCF Web API, WCF Data Servicesとはまた違うREST APIライブラリ

※ご注意
WCF Web APIはマイクロソフトにより現在開発はキャンセルされ、ASP.NET MVC 4のASP.NET Web APIとして制作・公開されています。

.NET Framework/ASP.NETでRESTfulなAPI構築を目的に記事を探されている方は是非以下のリンクからASP.NET Web APIについてご確認下さい。
http://opcdiary.net/?page_id=5981


WCF Web APIはWCF Data Servicesと同様にWCFでREST APIを持つServiceを構築するためのライブラリですが、Data Servicesが基本的にData Baseのテーブルに対してREST APIを構築する物であったのに対して、Web APIはもう少しDBに対して抽象度が上がり、オブジェクトモデルに対するREST APIを構築するためのライブラリとなっていて、通常のWEB開発者にとってはこちらの方が素直なイメージに近い物だと思います。また、通常のWCFのホスト方法とは別にASP.NETでもサービスをホスト可能となっており、特にASP.NET MVCとの親和性が高く、既存のASP.NET MVCのアプリケーションにREST APIを追加したいような場合や、AzureのWEB Roleに配置したい場合に向いていると思います。

WCF REST Starter kitをご存じの方はそれの後継と考えて良さそうです。(追記:1:11)

この記事はMSエバンジェリストの@chackさんのMSDN Blog記事「Web API を始めてみよう」を発展させて、まずEntity Framework Code Firstのモデルを用意して、そのモデルに対してREST APIを用意するというシナリオで進めていきたいと思います。ですので、そこまでは終わっている前提で進めていきます。
Continue reading WCF Web API, WCF Data Servicesとはまた違うREST APIライブラリ

C# eventのオーバーライドと基底クラスで発生するイベントの処理

C#のeventはvirtualが宣言できて、派生クラスでoverrideできますが、そのオーバーライドされたイベントに登録したイベントハンドラを基底クラス側から呼び出せません。これはeventは宣言された同一クラス内でのみ発生させることができると言うC#の言語仕様なので当たり前と言えば当たり前の動作なのですが、適切な処理をしていないがために基底クラス側でイベントを発生させたときにExceptionが発生してしまったりと言うことがあります。(別の言い方を知れば派生クラスから基底クラスのイベントを発生させることができません。)

まぁ頭の悪い子(俺)はそれでずっとうじうじ悩んだりするわけです。

具体的にはイベントをオーバライドしたら、そのオーバーライドしたイベントの基底クラスのイベントのイベントハンドラを用意し、そのイベントハンドラで、オーバーライドしたイベントを呼び出します。ようはイベントが伝達できるようにすればいいわけですねって、オーバーライドって文字がたくさん出てきて何かよくわかりませんね。と言うことでサンプルを以下にのせます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EventTest
{
    class Program
    {
        static void Main(string[] args) {
            Test test = new Test();
            test.TestEvent += new EventHandler(test_TestEvent);
            test.Fire();
            test.BaseFire();
            Console.Read();
        }

        static void test_TestEvent(object sender, TestEventArgs e) {
            Console.WriteLine(e.Message);
        }
    }

    //基底クラス
    public class TestBase
    {
        //イベントをvirtualで宣言する。
        internal virtual event EventHandler TestEvent;
        //イベントを発生させる
        public void BaseFire() {
            TestEventArgs args = new TestEventArgs("Fired on Base class");
            TestEvent(this, args);//派生クラス側で処理がないとイベントを発生できないので、ここでExceptionが発生する。
        }

    }

    //派生クラス
    public class Test : TestBase
    {
        internal override event EventHandlerTestEvent;

        public Test() {
            //基底クラスのイベントにイベント伝達用のイベントハンドラを登録する。
            base.TestEvent += new EventHandler(Test_TestEvent);
        }
        //イベント伝達用のイベントハンドラ
        void Test_TestEvent(object sender, TestEventArgs e) {
            //利用先に基底クラスのイベントを伝達する
            this.TestEvent(sender, e);
        }
        //イベントを発生させる
        public void Fire() {
            TestEvent(this, new TestEventArgs("Fired on Extended class"));
        }
    }

    public class TestEventArgs : EventArgs
    {
        public TestEventArgs(string message) {
            this.Message = message;
        }
        public string Message { get; set; }
    }
}

実行結果

Fired on Extended class
Fired on Base class

当たり前と言えば当たり前のコードなんですがeventのvirtual / override含めて書籍やネットにあまりサンプルが無いようなので載せてみました。

Linq to XML 入門 その4 結合(JOIN)その2

忘れた頃にやってくる連載記事です。

今回は、やらないと前回書いた左外部結合とグループ化結合について説明します。

また、サンプルで使用するXMLファイルで、前回との違いは、category.xmlにカテゴリを一つ追加しています。



  
    飲料
  
  
    前菜
  
  
    主菜
  
  
    デザート
  
  
    お持ち帰り
    

グループ化結合

グループ化結合は、階層データ構造を作成する場合に便利です。グループ化結合は、最初のコレクションの各要素と、2 番目のコレクションの相関関係を持つ要素のセットを組み合わせたものです。

使用するXMLは内部結合のものと同じです。

以下の例ではカテゴリごとの料理のリストを作成しています。

XDocument menu = XDocument.Load(@"..\..\menu.xml");
XDocument category = XDocument.Load(@"..\..\category.xml");
 
var menuList = from c in category.Descendants("Category")
               join m in menu.Descendants("item")
               on
                   (string)c.Attribute("id")
               equals
                   (string)m.Attribute("CategoryId")
               into menusByCategory
               select new {
                   ID = c.Attribute("id"),
                   CategoryName = c.Element("CategoryName").Value,
                   Menus = from me in menusByCategory select new { Name = me.Element("name").Value }
               };
 
foreach (var c in menuList) {
    Console.WriteLine("{0} - {1}", c.ID, c.CategoryName);
    foreach (var m in c.Menus) {
        Console.WriteLine("\t{0}", m.Name);
    }
}

1,2行目でXML文書を読み込みます。

5行目から今回新しく説明するポイントです。

5行目のjoin句で、4行目のfrom句でcategory.xmlから取り出したxmlのエレメントに結合するmenu.xmlのエレメントを指定します。

6行目からon句から始まり9行目までが結合条件で、この場合にはcategory.xmlがもつidアトリビュートとmenu.xml側が持つ CategoryIdアトリビュートの値の一致をもって結合するようにしています。アトリビュート同士の値が同値であることの確認には"=" (オペレータ)ではなくequals句を使う必要があります。正確には

from <左辺XML>

join <右辺XML>

on <左辺条件> equals <右辺条件>

となります。

10行目ではinto句を使ってcategory.xmlのエレメントが持つidアトリビュートごとにmenu.xmlのエレメントをグループ化して、category.xmlのエレメントに結合します。

14行目ではselectをネストして、グループ化された中からメニューの名前のリストを作成しています。

動作結果

d="1" - 飲料
       コーラ
       アイスコーヒー
       ブレンドコーヒー
       生ビール
d="2" - 前菜
       フレンチフライ
       湯で海老
       チーズ盛り合わせ
       オニオングラタンスープ
       シェフのお任せミニサラダ
       シェフのお任せスープ
d="3" - 主菜
       御殿場高原で育った子羊のロースト
       あしたか牛のフィレ肉を使ったビーフシチュー
       沼津港スズキのグリル
       焼津マグロのカルパッチョ
       あしたか牛のサーロインステーキ
d="4" - デザート
       韮山苺を使ったショートケーキ
       西浦みかんのババロワ
       朝霧高原の牛乳から作ったティラミス
d="5" - お持ち帰り

左外部結合

左外部結合は、2 番目のコレクションに相関関係を持つ要素があるかどうかに関係なく、最初のコレクションの各要素が返される結合です。LINQ を使用すると、グループ結合の結果に対して DefaultIfEmpty を呼び出すことで、左外部結合を実行できます。

以下の例は、カテゴリーID、カテゴリー名、メニュー名を表示するプログラムで、カテゴリーに対応するメニューが無くてもカテゴリーIDとカテゴリー名は表示します。

処理の手順は次のようになります。

最初手順ではグループ結合を使用して内部結合を実行します。今回の例ですと、先ほどと同じようにmenu.xmlのエレメントのリストは、 category.xmlのエレメントが持つidアトリビュート と一致する menu.xmlのエレメントに基づいて、category.xmlのエレメントの一覧に内部結合されます。

2 番目の手順では、右側のコレクションに一致する要素がない場合でも、最初 (左側) のコレクションの各要素を結果セットに含めます。これを行うには、グループ結合から一致する要素の各シーケンスで DefaultIfEmpty を呼び出します。以下の例では一致する menu.xmlのエレメントの各シーケンスで DefaultIfEmpty が呼び出されます。一致する menu.xmlのエレメントのシーケンスがすべての category.xmlのエレメントに対して空の場合、各 category.xmlのエレメントが結果コレクションに表示されるように、1 つの既定値を含むコレクションが返されます。

var menuList = from c in category.Descendants("Category")
               join m in menu.Descendants("item")
               on
                (string)c.Attribute("id")
               equals
                (string)m.Attribute("CategoryId")
               into menusByCategory
               from mx in menusByCategory.DefaultIfEmpty(
                new XElement("item", new XAttribute("id", c.Attribute("id").Value), new XElement("name", ""), new XElement("price", "")))
               select new {
                   ID = c.Attribute("id"),
                   CategoryName = c.Element("CategoryName").Value,
                   MenuName = mx.Element("name").Value
               };
 
foreach (var c in menuList) {
    Console.WriteLine("{0} - {1} \t:\t{2}", c.ID, c.CategoryName, c.MenuName);
}

11行目はメニューで使われていないカテゴリが表示できるように、DefaultIfEmptyメソッドでmenusByCategory内の各シーケンスを調べ、シーケンスが空でないならシーケンスの各要素をmxに入れ、シーケンスが空であるなら、規定値としてDefaultIfEmptyメソッドの引数で与えている値がすべて空のitemエレメントをmxに入れています。(ここでは値の無いエレメントを追加していますが、それが適切かどうかは場合によります。)

動作結果

id="1" - 飲料   :       コーラ
id="1" - 飲料   :       アイスコーヒー
id="1" - 飲料   :       ブレンドコーヒー
id="1" - 飲料   :       生ビール
id="2" - 前菜   :       フレンチフライ
id="2" - 前菜   :       湯で海老
id="2" - 前菜   :       チーズ盛り合わせ
id="2" - 前菜   :       オニオングラタンスープ
id="2" - 前菜   :       シェフのお任せミニサラダ
id="2" - 前菜   :       シェフのお任せスープ
id="3" - 主菜   :       御殿場高原で育った子羊のロースト
id="3" - 主菜   :       あしたか牛のフィレ肉を使ったビーフシチュー
id="3" - 主菜   :       沼津港スズキのグリル
id="3" - 主菜   :       焼津マグロのカルパッチョ
id="3" - 主菜   :       あしたか牛のサーロインステーキ
id="4" - デザート       :       韮山苺を使ったショートケーキ
id="4" - デザート       :       西浦みかんのババロワ
id="4" - デザート       :       朝霧高原の牛乳から作ったティラミス
id="5" - お持ち帰り     :

このように「お持ち帰り」はメニューに存在しませんが表示されています。

ということでひとまず結合を含むクエリ式の説明はこれで終わりです。

それではまた次回!(あるのかー)

これまでの記事:

参考図書:

Essential LINQ (Microsoft .NET Development Series)

Essential LINQ (Microsoft .NET Development Series)

Charlie Calvert

Addison-Wesley Professional 2009-03-22

売り上げランキング : 109833

Amazonで詳しく見る by G-Tools

プログラミングMicrosoft LINQ (マイクロソフト公式解説書 Microsoft Visual Studi)

プログラミングMicrosoft LINQ (マイクロソフト公式解説書 Microsoft Visual Studi)

小高 太郎 (株)オーパス・ワン

日経BPソフトプレス 2009-05-25

売り上げランキング : 43591

Amazonで詳しく見る by G-Tools

Linq to XML 入門 その4 結合(JOIN)

しばらく間が開いてしまいすいませんです。前回は基本的なクエリーまで説明したので、今回からはもう少し複雑なクエリー式の説明をします。

今回はJOINを説明します。

JOIN(結合)はLinqにおいてもリレーショナルデータベースの結合と同じく一定の条件の下データ同士を関連付けます。

結合(Join)の概念がちょっとわかりにくいという方はSQLの入門書で結合(Join)について勉強してみるといいと思います。このJOINあたりからが実際にはLinqの非常に強力な使用方法になっていきます。リレーショナルデータベースのデータでもないものを簡単な書式でJoinできるというのは実はすごいことなのです。

Continue reading Linq to XML 入門 その4 結合(JOIN)

XML to Linq 入門番外編 : XDocumet.Load()でProxyの例外が発生する場合

前回までのサンプルではXDocument.Load(”URL”)でRSSのフィードをロードしてしましたが、Proxy経由でのアクセスが必要な場合に、Loadメソッド実行時に例外が発生します。

Loadメソッドは引数で指定されたURIがhttpであった場合に内部的にWebアクセスしていると思われますが、そのときにProxyに対しては考慮していないようです。また、Loadメソッドの引数やXDocumentのプロパティではProxyの設定をする方法が無いので、このような場合にはLoadメソッドで直接URIを指定するのではなく、Proxyの設定ができるWebClientとXmlReaderを使ってWEBサーバからXMLファイルを取得し、ストリーム化し、最終的にXMLデータとして取得する必要があります。

以下がそのサンプルです。

using System.Xml;
using System.Net;
using System.IO;

WebClient web = new WebClient();
WebProxy myProxy = new WebProxy("proxy:8080", true);
myProxy.Credentials = CredentialCache.DefaultCredentials;
web.Proxy = myProxy;
Stream stream = web.OpenRead(@"http://www.isisaka.com/blog/index.xml");

XmlReader reader = XmlReader.Create(stream);


//XDocument rss = XDocument.Load(@"http://www.isisaka.com/blog/index.xml");
XDocument rss = XDocument.Load(reader);

5行目でWebClientクラスのインスタンスを作ります。

6行目でWebProxyクラスのインスタンスを作り、Proxyサーバアドレス等を設定し、7行目でそのProxyの認証のタイプを設定します。(この場合はNTLM認証です)

8行目でWebClientのインスタンスにProxyを設定します。

9行目ではWEBサーバよりXMLデータをStreamとして取得します。

11行目ではstreamになっているXMLデータをXmlReaderに変換します。

15行目でLinq to XMLでXMLデータを使用できるようにXmlReaderからXDocumentにXMLデータをロードします。

XDocumentクラスのLoadメソッドでのURI指定は便利ですが、ネットワーク環境によってはこのような処理が必要になるので注意してください。また今回特に例外処理を入れてないのですが、実際には部分部分で例外処理が必要になる場合があるのでその注意もお願いします。

.NETでのProxy設定については以下のKBが参考になります。

[PRB] HTTP プロキシ サーバー経由で Web サービスを使用する .NET クライアントでエラーが発生する

http://support.microsoft.com/kb/318140/

早いところ次回が書けるといいなぁ。ではまた次回!

Liunq to XML 入門 その3 (Linq クエリ構文)

今回は予定を変えてLinqのクエリ式の構文について説明します。前回クエリの方法について説明しましたが、クエリ式の構文についての説明はしていなかったので、前回説明した基本的なクエリ式の構文について説明します。

基本的なクエリ

Linqでの基本的なクエリ式は以下のようになります。

from [範囲変数] in [データソース]
select [範囲変数]

まず、クエリ式はfrom句から始める必要があります。つぎに最低でもselect句で範囲変数を指定し、最終的に式が返すソースシーケンスの内容を確定します。

from句

from [範囲変数] in [データソース]

from句ではクエリもしくはサブクエリの対象となるデータソースとソースシーケンス内の各要素を表すローカルの範囲変数を指定します。ソースシーケンスとはデータソースの中でLinq式内での各操作の対象となる連続したデータのことです。

LinqのデータソースにはIEnumerable<T>インターフェイスあるいはIEnumerableとその派生インターフェイスを実装したオブジェクトだけを指定することができます。通常の配列やArrayList、ADO.NETのデータセットはIEnumerableインターフェイスを持つのでLinqの対象とすることができます。

selsct句

select [式]

selsct句はクエリ式が実行されたときに生成される値の型を指定します。クエリ式の結果はselect句の前の式の評価およびselect句の式の評価によって生成されます。

select句の一番単純な例は式に範囲変数を指定し、ソースシーケンスをそのまま式の値にすることですが、以下の例のようにこの式でデータ変換をすることができます。

XDocument rss = XDocument.Load(@"http://www.isisaka.com/blog/index.xml");   
//select句でデータ変換する   
IEnumerable query = from x in rss.Element("rss").Elements("channel").Elements("item")
                              select DateTime.Parse(x.Element("pubDate").Value);   
foreach (var d in query) {   
    Console.WriteLine(d.ToLongDateString());   
}

この例では4行のselect句の式でXMLのバリュー(string型)のデータをDateTime型に変換しているので、クエリ式の結果をIEnumerble<DateTime>型の変数に格納することができます。

条件付きクエリ

先ほどのもっとも単純なクエリ式ではソースシーケンスのデータに対し、なんのフィルタリングもかけずに値を返していましたが、実際には何らかのフィルタリング条件をつけて必要なデータだけをソースシーケンスから取り出したいことが多いと思います。

クエリ式において、このフィルタリング条件を指定するのがwhere句です。

from [範囲変数] in [データソース]
whewe [条件式]
select [式]

この例では7秒目でToListメソッドを使ってLinq式の結果をメモリ上に確定しています。

これの詳しい話についてはMSDNライブラリの「クエリの結果をメモリに格納する (C# プログラミング ガイド)」を参照してください。

それでは、また次回。