Hatena::Groupmediaforcelabs

どうも、小松です。

2009-12-02

複数のプロパティを持ったAttribute

| 18:44

どうも、小松です。


以前のエントリで、プロパティが一つのカスタムAttributeを作成してみました。

今回は、複数のプロパティを持ったカスタムAttributeを作成してみます。


0. はじめに

開発環境は、以下のとおりです。

OSWindows 7 Enterprise
開発ツールVisual Studio 2008

1. Attributeの作成。

 1-1. プロジェクトを作成します。(名前は、「TestAttribute2」にしました。)

 1-2. Attributeを保存するフォルダ「Attributes」を作成します。

 1-3. Attributeを作成します。

  今回は、複数のプロパティを持ったMyAttributeAttributeを作成します。

  (Attributeを使用するとき、最後のAttributeを除いた名前で指定するため、こんな名前にしてしまいました。)

using System;

namespace TestAttribute2.Attributes
{
    public class MyAttributeAttribute : Attribute
    {
        private string _Attr1;
        private string _Attr2;
        private string _Attr3;

        public MyAttributeAttribute(string value)
        {
            _Attr1 = value;
        }

        public string Attr1
        {
            get { return _Attr1; }
            set { _Attr1 = value; }
        }

        public string Attr2
        {
            get { return _Attr2; }
            set { _Attr2 = value; }
        }

        public string Attr3
        {
            get { return _Attr3; }
            set { _Attr3 = value; }
        }

    }
}

2. Attributeを使用する。

 2-1. Personクラスを作成し、そこでMyAttributeAttributeを使用してみます。

 2-2. Personクラスを保存する「Entities」フォルダを作成します。

 2-3. Personクラスを作成し、Attributeのプロパティに値を入力します。

  コンストラクタ引数となる値は、そのまま値を指定します。

  その他のプロパティに値を入力するには、「プロパティ名 = 値」という形式で指定します。

using TestAttribute2.Attributes;

namespace TestAttribute2.Entities
{
    public class Person
    {
        [MyAttribute("id1", Attr2 = "id2", Attr3 = "id3")]
        public int id { get; set; }
    }
}

3. Attributeで設定した値を取得する。

 3-1. 確認のため、2で設定した値を取得したいと思います。

  MainPage.xamlのLayoutRootがロードされたときにPersonクラスのインスタンスを作成し、

  ボタンを用意し、ボタンをクリックしたら、PersonのAttributeの値を表示します。

 3-2. MainPage.xamlです。

  ボタンを一つ用意し、あとはイベントハンドラを指定します。

<UserControl x:Class="TestAttribute2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d"
    d:DesignWidth="640" d:DesignHeight="480">
    <Grid x:Name="LayoutRoot"
          Background="White"
          Loaded="LayoutRoot_Loaded">
        <Button x:Name="myButton"
                Width="100" Height="30"
                Content="get attributes"
                Click="myButton_Click"/>
    </Grid>
</UserControl>

 3-3. MainPage.xaml.csです。

using System;
using System.Reflection; // for PropertyInfo
using System.Windows;
using System.Windows.Controls;
using TestAttribute2.Attributes;
using TestAttribute2.Entities;

namespace TestAttribute2
{
    public partial class MainPage : UserControl
    {
        private Person person;

        public MainPage()
        {
            InitializeComponent();
        }

          private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            // Personをインスタンス化し、初期値を入力します。
            person = new Person() { id = 1 };
        }

        private void myButton_Click(object sender, RoutedEventArgs e)
        {
            string str = "";

            // personの型を取得します。
            Type type = person.GetType();

            foreach (PropertyInfo pInfo in type.GetProperties())
            {
                // pInfoからMyAttributeAttribute型のAttributeを取得します。
                MyAttributeAttribute attribute
                    = (MyAttributeAttribute)Attribute.GetCustomAttribute(pInfo, typeof(MyAttributeAttribute));

                // MyAttributeAttributeのプロパティの値を取得します。
                string attr1 = attribute.Attr1;
                string attr2 = attribute.Attr2;
                string attr3 = attribute.Attr3;

                // strにプロパティ名、値、MyAttributeAttributeのプロパティ値を追加します。
                str += pInfo.Name + ":\n"
                    + "  value: " + pInfo.GetValue(person, null) + "\n"
                    + "  attr1: " + attr1 + "\n"
                    + "  attr2: " + attr2 + "\n"
                    + "  attr3: " + attr3 + "\n";
            }

            // strをMessageBoxで表示します。
            MessageBox.Show(str);
        }
    }
}

4. 実行結果。

 f:id:coma2:20091202184003p:image

 正しく表示されました。

 コンストラクタ引数を複数にすることもできそうですね。

JenniferJennifer2012/02/18 04:08Felt so hopeless lokoing for answers to my questions...until now.

silvawyqngsilvawyqng2012/02/19 18:15ryRu8r <a href="http://ltsysdnmglod.com/">ltsysdnmglod</a>

epndcupjuyzepndcupjuyz2012/02/20 00:08KIudxT , [url=http://gmxujedmtivu.com/]gmxujedmtivu[/url], [link=http://elxaamasdvjj.com/]elxaamasdvjj[/link], http://vaxbpfqmfocj.com/

bgksgslaabgksgslaa2012/02/24 03:19Uppe0T <a href="http://xblbmgiquvty.com/">xblbmgiquvty</a>

2009-11-26

Timespanのフォーマット

| 14:32

どうも、小松です。


TimeSpanをtoString()メソッドで文字列にするときに、フォーマットを指定したいです。

「hh:mm:ss」とか[mm:ss]とか指定して文字列を取得したいです。

調べてみたところ、フォーマットを指定して文字列を取得するメソッドは、TimeSpanクラスにはなさそうです。


ないので、簡単なものを自分で作ってみました。

今回は、時間と分と秒のみを指定できるように指定しています。


1. 仕様。

 ・時間は「h」で指定する。

 ・分は「m」で指定する。

 ・秒は「s」で指定する。

 ・時間、分、秒ともに、文字を2つ並べた場合は2ケタ表示する。

  例:時間が「1」の場合、hhとしたら「01」と表示する。


2. フォーマットに従って、変換。

 指定したフォーマットに従って、TimeSpanを文字列に変換するメソッドを作成しました。

// 引数tsの値を、引数formatで指定した書式の文字列に変換する。
private string timeSpanFormatter(TimeSpan ts, string format)
{
    string ret = format;
    ret = ret.Replace("hh", ts.Hours.ToString("00"));
    ret = ret.Replace("h", ts.Hours.ToString("0"));
    ret = ret.Replace("mm", ts.Minutes.ToString("00"));
    ret = ret.Replace("m", ts.Minutes.ToString("0"));
    ret = ret.Replace("ss", ts.Seconds.ToString("00"));
    ret = ret.Replace("s", ts.Seconds.ToString("0"));
    return ret;
}

3. 確認。

 2で作成したメソッドを実際に使用してみます。

 実行結果は、ソースのコメントに書いています。

TimeSpan ts = new TimeSpan(1, 2, 30);
MessageBox.Show(timeSpanFormatter(ts, "h時間m分s秒"));     // 結果「1時間2分30秒」
MessageBox.Show(timeSpanFormatter(ts, "hh時間mm分ss秒"));  // 結果「01時間02分30秒」

4. 最後に。

 とりあえず、ほしい機能を実現することができたのですが、もっと簡単な方法を見つけてしまいまいた。

 Visual Basic 中学校 掲示板2というサイトにありました。

 メソッドを作成することなく、以下のように一行で文字列を取得できました。

MessageBox.Show(new DateTime(0).Add(new TimeSpan(1, 2, 30)).ToString("H時間m分s秒"));     // 結果「1時間2分30秒」
MessageBox.Show(new DateTime(0).Add(new TimeSpan(1, 2, 30)).ToString("HH時間mm分ss秒"));  // 結果「01時間02分30秒」

 以下、簡単な説明です。

  ・基準となるDateTimeをインスタンス化します。(日付は適当でよいですが、時間は、0時0分0秒にします)

  ・インスタンス化したDateTimeにフォーマット付き文字列で表したいTimeSpanを加算します。

  ・最後に、DateTime.ToString()メソッドを使用してフォーマットします。


 自分の頭の固さを痛感です。

CauaCaua2012/03/22 18:51Keep on writing and cuhgging away!

bnkongxrcebnkongxrce2012/03/22 22:06BI1B5F <a href="http://dxzsbouezfdk.com/">dxzsbouezfdk</a>

yfrqakwfitlyfrqakwfitl2012/03/23 19:493r20Wb , [url=http://dndfmdmwdarp.com/]dndfmdmwdarp[/url], [link=http://zvkwbbcqbiux.com/]zvkwbbcqbiux[/link], http://sdgzffquugtk.com/

eviemjnneviemjnn2012/03/24 02:17hm8aDr <a href="http://nmdqozihbbwa.com/">nmdqozihbbwa</a>

2009-11-25

AnnotationならぬAttribute

| 19:21

どうも、小松です。


JavaでいうところのAnnotation(アノテーション)をSilverlight(C#)で使いたいと思ったのですが、

検索してもなかなか見つかりません。

Validationで使用するAnnotationは見つかるのですが、カスタムのAnnotationを作成する方法は

なかなか見つかりません。

ようやく辿り着いたのがブログの記事で、.NetではAttribute(アトリビュート)が似た役割を持っているそうです。

いい情報をありがとうございます。(長い英語なのでちゃんと読んでませんが)


とりあえずAttributeを使えばいいということがわかったので試してみたいと思います。

0. はじめに

開発環境は、以下のとおりです。

OSWindows Server 2008 R2 Standard
開発ツールVisual Studio 2010 Ultimate Beta2

1. Attributeの作成。

 1-1. プロジェクトを作成します。(名前は、「TestAttribute」にしました。)

 1-2. Attributeを保存するフォルダ「Attributes」を作成します。

 1-3. Attributeを作成します。

  今回は、エンティティのプロパティの略称を付与するShortNameAtributeを作成します。

using System;

namespace TestAttribute.Attributes
{
    // Attributeクラスを継承する。
    public class ShortNameAttribute : Attribute
    {
        private string _Name;

        // コンストラクタは、Attributeが設定されるときに呼ばれる。
        public ShortNameAttribute(string value)
        {
            _Name = value;
        }

        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                _Name = value;
            }
        }
    }
}

2. Attributeを使用する。

 2-1. Personクラスを作成し、そこでShortNameAttributeを使用して見ます。

 2-2. Personクラスを保存する「Entities」フォルダを作成します。

 2-3. Personクラスを作成します。各プロパティの略称を指定します。

using TestAttribute.Attributes;

namespace TestAttribute.Entities
{
    public class Person
    {
        [ShortName("i")]
        public int id { get; set; }

        [ShortName("fn")]
        public string FirstName { get; set; }

        [ShortName("ln")]
        public string LastName { get; set; }

        [ShortName("a")]
        public int Age { get; set; }
    }
}

3. Attributeで設定した値を取得する。

 3-1. 確認のため、2で設定した値を取得したいと思います。

  MainPage.xamlのLayoutRootがロードされたときにPersonクラスのインスタンスを作成し、

  ボタンを用意し、ボタンをクリックしたら、PersonのAttributeの値を表示します。

 3-2. MainPage.xamlです。

  ボタンを一つ用意し、あとはイベントハンドラを指定します。

<UserControl x:Class="TestAttribute.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot"
          Background="White"
          Loaded="LayoutRoot_Loaded">
        <Button x:Name="myButton"
                Width="100" Height="30"
                Content="get attributes"
                Click="myButton_Click"/>
    </Grid>
</UserControl>

 3-3. MainPage.xaml.csです。

using System;
using System.Reflection; // for PropertyInfo
using System.Windows;
using System.Windows.Controls;
using TestAttribute.Attributes;
using TestAttribute.Entities;

namespace TestAttribute
{
    public partial class MainPage : UserControl
    {
        private Person person;

        public MainPage()
        {
            InitializeComponent();
        }

        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            // Personをインスタンス化し、初期値を入力します。
            person = new Person() { id = 1, FirstName = "太郎", LastName = "メディア", Age = 33 };
        }

        private void myButton_Click(object sender, RoutedEventArgs e)
        {
            string str = "";

            // personの型を取得します。
            Type type = person.GetType();

            foreach (PropertyInfo pInfo in type.GetProperties())
            {
                // pInfoからShortNameAttribute型のAttributeを取得します。
                Attribute attribute = Attribute.GetCustomAttribute(pInfo, typeof(ShortNameAttribute));

                // ShortNameAttributeのNameプロパティの値を取得します。
                string name = ((ShortNameAttribute)attribute).Name;

                // strにプロパティ名、値、ShortNameAttributeのNameプロパティ値を追加します。
                str += pInfo.Name + ":\n"
                    + "  value: " + pInfo.GetValue(person, null) + "\n"
                    + "  short name: " + name + "\n";
            }

            // strをMessageBoxで表示します。
            MessageBox.Show(str);
        }
    }
}

4. 実行結果。

 f:id:coma2:20091125191429p:image

 正しく表示されました。

 次は、複数のプロパティを保持したAttributeについて調べてみたいと思います。


 **2009/12/02追記 ここから**

 複数のプロパティを持ったAttributeを試してみました。

 **2009/12/02追記 ここまで**

HelenaHelena2012/02/20 13:51Good job miakng it appear easy.

pwkzswpqipppwkzswpqipp2012/02/21 18:14iIgpZi <a href="http://nivnptrvjbsq.com/">nivnptrvjbsq</a>

katkzmetkatkzmet2012/02/21 23:01huFkYG , [url=http://shhgniakqehb.com/]shhgniakqehb[/url], [link=http://dejpkuldllcq.com/]dejpkuldllcq[/link], http://fztdszwizlcx.com/