tmori3y2のブログ

主にWindowsのプログラムなど

リフレクションでプロパティの設定/取得をする拡張メソッドを持つ空のインターフェースは有りなのか?

このブログを始めたのは、インターネットでROMったり、フォーラムで質問しても中々自分の疑問を解消出来ないような気がしたので、情報発信をしていくことで、帰ってくるレスポンスの中に答えがあるんじゃないかと考えたのが動機です。

もっとも、皆さんにスルーされちゃうようなネタばかりだと、全くレスポンスも来ないので、内容が肝心ですが・・・

というわけで、よろしくご指導お願いします。

さて、本題ですが、MFCのクライアントアプリケーションで、キー名でアクセスするvariantコレクションでデータを扱っていて、その編集画面をどうしてもWPF 4.5+MVVMのUserControlで実装したくなりました。

相互運用経由で、Modelのプロパティにアクセスする場合は、キー名をプロパティ名に変換して、マネージのどこかの層でリフレクションを使い、プロパティ名によるobject型(variant)の値の操作を行うのが自然な流れだろうと考えたわけで。

最初はPrismのBindableBaseを派生させたクラスに、リフレクションでプロパティにアクセスするSetProperty()/GetProperty()を実装したのだけど、WPFとしては不要なローレベルなインターフェースを直接実装するのも変だと思いつつも、Model本体に毎回コードスニペットなどで張り付けるのも何だかイマイチな気がした。

そもそも相互運用しなくなった暁には、WPFとしては不要なインターフェースなので、要らなくなった時に取り外しが出来ないか?と考えた。

そいつがお題のリフレクションでプロパティの設定/取得をする拡張メソッドを持つ空のインターフェース。

public interface IPropertySupportImp {}

public static IPropertySupportImpExtensions
{
    public static object GetProperty(this IPropertyHelperImp self, string propertyName)
    {
        // リフレクションでごにょごにょ・・・
    }

    public static void SetProperty(this IPropertyHelperImp self, string propertyName, object value)
    {
        // リフレクションでごにょごにょ・・・
    }
}

CA1040: 空のインターフェイスは使用しないでください

って、Code Analysisで怒られましたが、ちゃんと動いています。

当初の取り外しを実現するなら、インターフェースとは別の独自の名前空間で定義するとusingで付け外しができる。

(脱線するが、こういう時にImpって使えるんだね・・・って、どうでも良い話だけど)

ちょっと経ってから、本家のMSDNJavaのinterfaceのstatic methodみたいのをC#に実装する予定はないの?って質問があったので、面白がって拡張メソッドで似たようなことが出来るから要らないんじゃないか?ってコメント付けてみた。

サンプルが何か無いかと考えていた時に、Prism.Mvvm.PropertySupport.ExtractPropertyName()が長ったらしいので、短く書けるように敢えてstaticじゃないメソッドで包んで、先ほどのベースクラスに追加した時に、

CA1822: メンバーを static に設定します

って、Code Analysisで怒られたことを思い出した。

    public static string NameOf<T>(this IPropertySupportImp self, Expression<Func<T>> propertyExpression)
    {
        // 別にこのくらいはPrism使うほどじゃないけど、一応そのまま書いておきます
        return Prism.Mvvm.PropertySupport.ExtractPropertyName<T>(propertyExpression);
    }

ほら、こうしたら、ベースクラスを汚さずにthis.NameOf(() => PropertyA)とか短く書けるよね?って、もちろん、C#6.0では不要なのでC#5.0までの話ですよ。(私は、未だC#5.0始めたばかりなので助かってますが・・・)

原文はこちら。英語、下手糞だから意図通じてるんだろうかね?

Roadmap for implementing Interfaces for Static Methods

ちなみに、Javaはinterface継承しちゃったら簡単には外せない。

大体、「この方法でinterfaceにmain()が実装できる」ってネットで検索してたら出てきたけど何?

(多分)テストにしか使わないメソッドが外せなくて良いのか?

拡張メソッドならいつでも外せるからC#の方が凄いじゃないか!

って。

でも、いろいろググるとmix-inというキーワードと一緒にC#の例が色々出てきます。威張るほどのことじゃなかったですね・・・

検索した限りは、概ねこういう使い方は有りって感じだけど、ただの自己満足なのか、本当の所はどうなんだろうか・・・

何か自信が無くなってきました。

気軽にコメントしてください。お待ちしています。