C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2008/01/31 00:26
今まで LINQ to Object の基本くらいしか知らなかったので、今日は大収穫を得た。
一番の収穫はやはり LINQ to SQL。
つか、LINQ to SQL の場合、where 句のラムダ式が SQL の where 句に変換されるというのは、正直半信半疑だった。
で、帰宅して早速試してみた。

static void Main(string[] args)
{
    DataContext context = new DataContext(Settings.Default.Database1ConnectionString);
    var query =
        from target in context.GetTable<Table1>()
        where (target.Column1 == "a")
        select target;

    string queryText = query.ToString();
    Console.WriteLine(queryText);
}

[Table(Name = "Table1")]
class Table1
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int PrimaryKey;

    [Column]
    public string Column1;
}

実行結果
SELECT [t0].[PrimaryKey], [t0].[Column1]
FROM [Table1] AS [t0]
WHERE [t0].[Column1] = @p0


Σ(゚д゚lll)ガーン

ホントに where 句が where 句に・・・!
そういや、LINQ to SQL のラムダ式はデリゲートではなく System.Linq.Expressions.Expression オブジェクトに変換されると言っていたな。
逆コンパイルしてみると、確かに・・・つーか結構複雑なことやってるな。target.Column1 == "a" というラムダ式から、target とか Column1 とか == 演算子なんかのメタデータを採取して、それを元に Expression オブジェクトを構築するようなコードへと変換されている。
なるほどなるほど。

でもまぁこんなクエリー式はさすがに無理だろ。

var query =
    from target in context.GetTable<Table1>()
    where (target.Column1[1].ToString() == "a")
    where (target.Column1.IndexOf("b") <= 3)
    select target;

実行結果
SELECT [t0].[PrimaryKey], [t0].[Column1]
FROM [Table1] AS [t0]
WHERE ((
    (CASE
        WHEN (DATALENGTH(@p0) / 2) = 0 THEN CONVERT(BigInt,0)
        ELSE CONVERT(BigInt,(CONVERT(Int,CHARINDEX(@p0, [t0].[Column1]))) - 1)
     END)) <= @p1) AND ((CONVERT(NVarChar(MAX),CONVERT(NChar(1),SUBSTRING([t0].[Column1], @p2 + 1, 1)))) = @p3)




( ゚Д゚ ) ・・・。



タグ: .NET C# ADO.NET LINQ
2007/09/26 20:05
どうでもいいっちゃどうでもいいことですが、下の2つのページを見比べると、URL の最後の方に "(VS.80)" が付いていない方のページでは、「重要」という項目が表示されています。この「重要」の中で、.NET Framework 2.0 以降ではこのインターフェイスの代わりに ConfigurationSection クラスから派生するように、と書かれています。"(VS.80)" が付いている方のページではこのことが書かれていません。

"(VS.80)" 有り
IConfigurationSectionHandler インターフェイス (System.Configuration)

"(VS.80)" 無し
IConfigurationSectionHandler インターフェイス (System.Configuration)


で、今度は ConfigurationSection クラスだと、"(VS.80)" が付いている方には「メモ : このクラスは、.NET Framework version 2.0 で新しく追加されたものです。」と書かれているのに "(VS.80)" が付いていない方には書かれていません。

"(VS.80)" 有り
ConfigurationSection クラス (System.Configuration)

"(VS.80)" 無し
ConfigurationSection クラス (System.Configuration)


しかも、よくよく眺めてみると、他にもちらほら違いがあります。
で、更によくよく見ると、"(VS.80)" が付いているページと付いていないページとでは、ページ階層も異なるようで、"(VS.80)" が付いているページは「以前のバージョン」というページの下の方にぶらさがっているようです。


まぁ、だからどうしたと言う訳でもなく、ただそれだけです。
ページによっては、URL から "(VS.80)" を除いたとしても勝手に補完される場合もあるようです。
タグ: .NET MSDN
2007/09/17 21:28
けっこうややこしいのでメモ。

static void Main()
{
    Image page1 = new Bitmap("C:\\work\\page1.bmp");
    Image page2 = new Bitmap("C:\\work\\page2.bmp");
    Image page3 = new Bitmap("C:\\work\\page3.bmp");

    // まず、1ページ目となる画像を指定しておく。
    Image tiff = new Bitmap(page1);

    // TIFF 形式のエンコーダ。
    ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
    Predicate<ImageCodecInfo> tiffEncoderPredicate =
        delegate(ImageCodecInfo input)
        {
            return (input.FormatID == ImageFormat.Tiff.Guid);
        };
    ImageCodecInfo tiffEncoder = Array.Find(imageEncoders, tiffEncoderPredicate);

    // エンコーダのパラメータ。
    EncoderParameters tiffEncoderParameters = new EncoderParameters(1);
    tiffEncoderParameters.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);

    // 作業領域となるメモリストリーム。
    MemoryStream tiffStream = new MemoryStream();
    // Save メソッドによって、1ページ目が保存され、更に Image オブジェクトとメモリストリームが関連付けられる。
    tiff.Save(tiffStream, tiffEncoder, tiffEncoderParameters);

    // 2ページ目, 3ページ目の保存に使用するエンコーダのパラメータ。
    EncoderParameters pageEncoderParameters = new EncoderParameters(2);
    pageEncoderParameters.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
    pageEncoderParameters.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone);

    // 先ほどの Save メソッドで関連付けられたメモリストリームに対して保存される。
    tiff.SaveAdd(page2, pageEncoderParameters);
    tiff.SaveAdd(page3, pageEncoderParameters);

    // メモリストリームの内容をファイルに保存する。
    File.WriteAllBytes("C:\\work\\test.tif", tiffStream.ToArray());
}



EncoderParameter のインスタンスを生成する際、EncoderValue 列挙値を long にキャストして渡しています。これは int ではなく long にしなければいけません。でないと失敗します。

サンプルなんで Dispose メソッドは呼び出してません。Image, MemoryStream  以外にも、EncoderParameters や EncoderParameter も IDisposable を実装してます。
タグ: .NET C#
2007/06/30 16:18
オンラインの MSDN ライブラリの方も、.NET Framework 3.0 関連のページが日本語化されてますね。
このブログの WCF の記事、全部日本語ページへのリンクに張り替えないと。。。
タグ:
2007/03/07 10:59
やっと出ました、 Visual Studio 2005 Service Pack 1 Update for Windows Vista !

ダウンロードの詳細 : VS2005 SP1 Update for Vista
タグ: .NET C#
2007/01/23 14:52

HttpCapabilitiesBase.JavaScript プロパティ

すごいなこれ^^;
まぁ、以下の部分が理由でしょうね。


ブラウザが JavaScript をサポートしていても、セキュリティの設定でスクリプトが無効になっている場合、JavaScript プロパティは true を返しますが、ブラウザでスクリプトは実行されません。

タグ: .NET C# MSDN
2006/12/21 20:20
.NET Framework 3.0 がリリースされて少し経ちましたが、僕はまだ WPFにもWCFにもWFにも手を出していませんでした。
でも、最近入ってきた仕事でWCFを使ったWebサービスの開発を行うことになりそうです。
今はWCFの調査段階で、サンプルプログラムの作成中。そして、「そうだ、クライアント側はWPFで作ろう」という素晴らしい名案が浮かびましたので、WPFの調査も ( 勝手に ) 行っています。
WCFとWPFのお勉強を業務の一環としてできるという、なんともラッキーな状況です。 ( まぁ、さすがにWPFの方は深くつっこんで勉強するわけにはいきませんが^^; )

とりあえず、WCFの勉強に使っているサイトと、WPFの勉強に使おうと思っているサイトを貼り付けておきます。

Windows Communication Foundation概説 − @IT

WPF アプリケーションを作る クッキングガイド


あと、↓の辺も抑えておきたいですね。 ( オレが。 )

Windows Communication Foundation アーキテクチャの概要

Windows Communication Foundation による高信頼メッセージングについて

Windows Presentation Foundation - ホーム


.NET Framework 3.0 や、Visual Studio 2005でWPF/WCF開発を行うためのアドインの入手に関しては、こちらの記事を参照してください。

.NET Framework 3.0 正式版 リリース
タグ: .NET C# WPF WCF
2006/12/20 10:53
もう、公開されてから何日か経っているのですが、一応。

Visual Studio 2005 Service Pack 1


他の方のブログを見ていると、既にいくつかのバグが発見されていますね。
タグ: .NET C#
2006/10/20 01:49
MSDNに記載されている、Delegate.DynamicInvokeメソッドの例外に関する情報が間違ってる。
MSDNには以下のように記載されている。


[ MemberAccessException ]
呼び出し元には、(たとえば、メソッドがプライベート メソッドの場合に) デリゲートが表すメソッドへのアクセス権がありません。 または args にリストされているパラメータの数、順序、または型が無効です。

[ TargetException ]
デリゲートが表すメソッドがインスタンス メソッドであり、対象オブジェクトが null 参照 (Visual Basic では Nothing) です。 または デリゲートが表すメソッドが、そのメソッドをサポートしないオブジェクトまたはクラスに対して呼び出されています。

[ TargetInvocationException ]
カプセル化されたメソッドの 1 つが例外をスローします。


しかし、TargetInvocationException以外の例外&説明は、実際と全く異なる。

第一に、デリゲートが表すメソッドがプライベートメソッドだろうが、そのメソッドがプライベートメソッドを呼び出していようが、例外なんて発生しない。また、デリゲートが表すメソッドの要求するアクセス許可が呼び出し元になくて、System.Security.SecurityExceptionがスローされる場合も、MemberAccessExceptionなどスローされず、 ( SecurityExceptionをラップした ) TargetInvocationExceptionがスローされる。

第二に、argsにリストされているパラメータの数、順序、型が無効な場合でも、MemberAccessExceptionはスローされない。パラメータ の数が不正な場合はTargetParameterCountExceptionがスローされ、順序や型が向こうな場合は ArgumentExceptionがスローされる。

第三に、 「 デリゲートが表すメソッドがインスタンス メソッドであり、対象オブジェクトがnull参照 」 なんて状況はありない。 「 対象オブジェクトがnull参照 」 というのは、対象オブジェクトがGCに回収されている状況を指しているのだろうが、デリゲートが存在する限り対象オブジェクトがGCに回収されることはない。デリゲートのTargetプロパティにしっかりと対象オブジェクトの"強い"参照が保持されているから。

第四に、 「 デリゲートが表すメソッドが、そのメソッドをサポートしないオブジェクトまたはクラスに対して呼び出されています。  」 なんて状況もありえない。
まず、以下のように、デリゲートオブジェクトを普通に作成した場合、当然、メソッドとオブジェクトは正しく結びつく。
public delegate void SimpleMethod();

class Class1
{
    public Class1()
    {
    }

    public void Method1()
    {
        Console.WriteLine("Method1 was called.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Class1 obj = new Class1();
        Delegate objMethod1 = (SimpleMethod)obj.Method1;
        objMethod1.DynamicInvoke();
        Console.ReadLine();
    }
}

また、リフレクションを使って作成したとしても、無関係のオブジェクトと関連付けて作成することは不可能である。
public delegate void SimpleMethod();

class Class1
{
    public Class1()
    {
    }

    private void Method1()
    {
        Console.WriteLine("Method1 was called.");
    }
}

class Program
{
    static void Main(string args)
    {
        Assembly thisAssembly = Assembly.GetExecutingAssembly();
        Type class1 = thisAssembly.GetType("Class1");
        MemberInfo[] class1Member = class1.GetMember("Method1", MemberTypes.Method, BindingFlags.Instance | BindingFlags.NonPublic);
        MethodInfo class1Method1Info = class1Member[0] as MethodInfo;
        // 以下のコードでは、実行時に例外がスローされる。
        // Delegate class1Method = Delegate.CreateDelegate(typeof(SimpleMethod), new Object(), class1Method1Info);
        Delegate class1Method = Delegate.CreateDelegate(typeof(SimpleMethod), new Class1(), class1Method1Info);
        class1Method.DynamicInvoke();
        Console.ReadLine();
    }
}

( ついでに、対象メソッドの可視性はプライベートにしてある。 )


で、結局のところ、Delegate.DynamicInvokeメソッドの例外は、正しくは以下のようになる。

[ System.ArgumentException ]
args にリストされているパラメータの順序、または型が無効である場合にスローされる。

[ System.Reflection.TargetParameterCountException ]
args にリストされているパラメータの数が、必要なパラメータ数と異なる場合にスローされる。

[ System.Reflection.TargetInvocationException ]
カプセル化されたメソッドの 1 つが例外をスローする場合にスローされる。
タグ: C# .NET
2006/09/24 01:04
なんか忘れがちなのでメモ。

テキストファイルやXMLファイルなど、全てのファイルはアセンブリに埋め込んで利用することができる。

ファイルをアセンブリに埋め込むには、ファイルのプロパティ項目の [ ビルド アクション ] を、 " 埋め込まれたリソース " に設定してビルドする。

埋め込まれたリソースを利用するには、以下のようにリフレクションを利用する。

埋め込まれたリソース"Hoge.txt"を取得する例
using System;
using System.IO;
using System.Reflection;

namespace YokoKen.Sample
{
    static class Program
    {
        void Main()
        {
            string outputText;
            Assembly thisAssembly = Assembly.GetExecutingAssembly();
            using (Stream resourceStream = thisAssembly.GetManifestResourceStream("YokoKen.Sample.Hoge.txt"))
            {
                using (StreamReader resourceReader = new StreamReader(resourceStream))
                {
                    outputText = resourceReader.ReadToEnd();
                }
            }
            Console.WriteLine(outputText);
            Console.ReadLine();
        }
    }
}

注意すべきは、AssemblyオブジェクトのGetManifestResourceStreamメソッドに渡すファイル名には、名前空間を含める必要があるということだ。この名前空間はプロジェクトのプロパティ項目の [ 規定の名前空間 ] に設定してある名前空間(サブディレクトリに配置した場合、これにディレクトリ階層が加えられた名前空間)である。
タグ: .NET C#