SearchAPIはhttp://search.twitter.com/で検索した結果と同じようなものを取得できます。
今まで書き忘れていましたが、twitterのAPIは以下で公開されています。
http://apiwiki.twitter.com/
SearchAPI使う上で困るのは、戻ってくるJsonデータのフォーマットが違うことです。
どこで違いを吸収しようかなと、ViewModelレベルで分けたり試行錯誤しましたが、
Modelの最小限で違いを表すことにしました。
(ちなみにViewModelレベルまで違いを持ち込むと、
UI表示上の動作の違いは作りやすくなるかわりに
クラスの増加、コードの重複が多くなりそうな気がします。)
今回は小さな変更点が多数の箇所にあるので、
要点だけを書きます。詳細はソースコード参照。
まず、通常APIとSearchAPIの共通データを表現するインターフェイスを作ります。
前回までViewModelが直接Statusを参照していましたが
上記クラスを参照するようにします。
あとはITimelineItemクラスを実装するクラスをそれぞれのAPI用に
2つ(TwitterItemクラスとSearchTwitterItemクラス)作り、
それぞれがAPI専用の実際のデータを持つStatusクラス(※APIごとに名前変えた方がよかったかも)
を作ります。
あとはそれらのデータをURLから読み込む部分が異なりますので、
そこだけクラスに抽出します。
まずインターフェイス。
SearchAPIの方の実装。(もう一方は略)
SearchResultクラスとして読み込んでいますが、
これまでのAPIはStatusの配列を渡してきたのに対して
SearchAPIはStatusの配列を持った1つのオブジェクトを渡してくるため、
その違いを吸収するクラスです。
あとはSettingクラスも派生させて、検索ワードなどの差分を追加しています。
オプションダイアログ上の違い(クラスが異なるのに1つのリストに表示する)は
以下のように2つのDataTemplateを作ることで実現しています。
毎回ですが、説明がうまくできない。。
今回のソースコード
http://wtwitter.codeplex.com/SourceControl/changeset/view/41131
SearchAPI使う上で困るのは、戻ってくるJsonデータのフォーマットが違うことです。
どこで違いを吸収しようかなと、ViewModelレベルで分けたり試行錯誤しましたが、
Modelの最小限で違いを表すことにしました。
(ちなみにViewModelレベルまで違いを持ち込むと、
UI表示上の動作の違いは作りやすくなるかわりに
クラスの増加、コードの重複が多くなりそうな気がします。)
今回は小さな変更点が多数の箇所にあるので、
要点だけを書きます。詳細はソースコード参照。
まず、通常APIとSearchAPIの共通データを表現するインターフェイスを作ります。
public interface ITimelineItem : IEquatable<ITimelineItem> { /// <summary> /// ID番号 /// </summary> long Id { get; } ・・略 }
前回までViewModelが直接Statusを参照していましたが
上記クラスを参照するようにします。
public class TimelineItemViewModel { public TimelineItemViewModel(ITimelineItem item) { _item = item; }
あとはITimelineItemクラスを実装するクラスをそれぞれのAPI用に
2つ(TwitterItemクラスとSearchTwitterItemクラス)作り、
それぞれがAPI専用の実際のデータを持つStatusクラス(※APIごとに名前変えた方がよかったかも)
を作ります。
あとはそれらのデータをURLから読み込む部分が異なりますので、
そこだけクラスに抽出します。
まずインターフェイス。
public interface IItemsReader { /// <summary> /// /// </summary> /// <param name="source">入力ストリーム</param> /// <returns>解析結果(タイムラインのアイテム)</returns> IEnumerable<ITimelineItem> Read(Stream source); }
SearchAPIの方の実装。(もう一方は略)
class SearchTwitterItemsReader : IItemsReader { #region IItemsReader メンバ public IEnumerable<ITimelineItem> Read(System.IO.Stream source) { var serializer = new DataContractJsonSerializer(typeof(SearchResult)); var result = serializer.ReadObject(source) as SearchResult; foreach (var item in result.Results) { yield return new SearchTwitterItem(item); } } #endregion }
SearchResultクラスとして読み込んでいますが、
これまでのAPIはStatusの配列を渡してきたのに対して
SearchAPIはStatusの配列を持った1つのオブジェクトを渡してくるため、
その違いを吸収するクラスです。
あとはSettingクラスも派生させて、検索ワードなどの差分を追加しています。
オプションダイアログ上の違い(クラスが異なるのに1つのリストに表示する)は
以下のように2つのDataTemplateを作ることで実現しています。
<Window x:Class="WTwitter.View.OptionDialog" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:opt="clr-namespace:WTwitter.Model.UserData" Title="オプション設定" Width="400" Height="400" Loaded="Window_Loaded"> <Window.BindingGroup> <BindingGroup/> </Window.BindingGroup> <Window.Resources> <DataTemplate DataType="{x:Type opt:TimelineSetting}"> <GroupBox Header="タイムライン"> <StackPanel> <DockPanel> <TextBlock DockPanel.Dock="Left">表示名</TextBlock> <TextBox Text="{Binding Path=Name}" DockPanel.Dock="Left" MinWidth="50"/> <CheckBox Content="Auth" IsChecked="{Binding Path=IsAuthRequired}"/> </DockPanel> <DockPanel> <TextBlock DockPanel.Dock="Left">URL</TextBlock> <TextBox Text="{Binding Path=Url}"/> </DockPanel> </StackPanel> </GroupBox> </DataTemplate> <DataTemplate DataType="{x:Type opt:SearchTimelineSetting}"> <GroupBox Header="検索タイムライン"> <StackPanel> <DockPanel> <TextBlock DockPanel.Dock="Left">表示名</TextBlock> <TextBox Text="{Binding Path=Name}" DockPanel.Dock="Left" MinWidth="50"/> <CheckBox Content="日本語のみ対象" IsChecked="{Binding Path=IsJapaneseOnly}"/> </DockPanel> <DockPanel> <TextBlock DockPanel.Dock="Left">検索ワード</TextBlock> <TextBox Text="{Binding Path=SearchText}"/> </DockPanel> </StackPanel> </GroupBox> </DataTemplate> </Window.Resources>
毎回ですが、説明がうまくできない。。
今回のソースコード
http://wtwitter.codeplex.com/SourceControl/changeset/view/41131
0 件のコメント:
コメントを投稿