050plusの留守番電話設定
仕事用の電話番号が欲しかったので、050plus契約してiPhoneで使ってます。
今のところ3G回線でも一部地域を除き、ほぼ問題なく通話できています。*1
そんな感じで完璧ではないけど、まぁいいかなという感じで契約してから半年くらい使ってます。
つい昨日、最も不便だと思ってた留守電機能が標準で搭載されていることを知ったので慌てて設定しました。*2
初期設定は無効化されているので、アプリの管理メニューから留守番電話設定を行う必要があります。
自分が最適だと思える設定まで持っていくのに少し戸惑ったので、メモしておきます。
留守番電話機能の起動条件
050plusアプリが起動している、またはバックグラウンドで生きている場合は、
留守番電話センターへ繋ぎに行きません。こちらが通話開始するor向こうが切るまで延々コールし続けます。
アプリが起動されていない場合に電話がかかってくると、ワンコールくらいで留守番電話センターへ接続し、メッセージ録音ができます。
通知方法
留守番電話設定の「通知方法」を"全て通知"にします。
そうしないと、メッセージが録音されたときだけ着信案内メールが届くようになってしまいます。
音声ファイル
留守番電話設定の「音声ファイル」を"添付する"にします。
メッセージ(が存在する場合)は着信案内メールを受信するだけでメッセージの確認が行えますし、
留守番電話センターでのメッセージ確認がかなり面倒*3なので、この設定1択じゃないでしょうか。
新しい非同期呼び出し(async,wait)を試す
.NET4.5から導入される新しい非同期呼び出し。
こんな感じで使うようです。
public partial class Form1 : Form { public Form1() { InitializeComponent(); } //内部で非同期処理を行うメソッドにはasyncをつける private async void button1_Click(object sender, EventArgs e) { //戻り値を返す非同期処理の実行。awaitをつけて非同期処理であることを明示する。 textbox1.Text = await HeaveyProcess(); //voidな非同期処理の実行 StopWatch(5); } private async Task<string> HeaveyProcess() { await Task.Delay(TimeSpan.FromSeconds(3.0)); return "重い処理が完了しました!!"; } private async void StopWatch(int sec) { Console.WriteLine("開始:{0}", DateTime.Now); await Task.Delay(TimeSpan.FromSeconds(sec * 1.0F)); Console.WriteLine("終了:{0}", DateTime.Now); } }
参考サイト
複雑なラムダ式
最近、ASP.NETMVCのソースコードを読んでいるのだが、そこでは複雑なラムダ式が多々でてくる。
今回はその一例としてアクションフィルタの処理(ControllerActionInvokerクラスのInvokeActionMethodWithFiltersメソッド)を自分なりに解釈し、コードを起こしたものを載せておく。
いくつか有用そうなテクニックを盗めたし、
ASP.NET MVCのソースコードは本当に勉強になります。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LinqSample { public interface IActionParameter { object GetParameter(); } public class GenericParameter<T> : IActionParameter { private T val; public GenericParameter(T val) { this.val = val; } public object GetParameter() { return val; } } public class ActionResult { public object Value { get; set; } } public class ActionContext { public ActionResult CurrentValue { get; set; } public ActionContext() { CurrentValue = new ActionResult() { Value = "" }; } } public static class Action { public static ActionResult ConcatString(Func<ActionResult> action, IActionParameter param) { ActionResult current = action(); var newValue = current.Value.ToString() + param.GetParameter().ToString(); current.Value = newValue; Console.WriteLine(current.Value); return current; } public static ActionResult GetMaxValue(Func<ActionResult> action, IActionParameter param) { int tpResult; if (!int.TryParse(param.GetParameter().ToString(), out tpResult)) throw new ArgumentException("パラメーター不正(param)"); var current = action(); if (!int.TryParse(current.Value.ToString(), out tpResult)) throw new ArgumentException("パラメーター不正(action)"); var newValue = ""; if (Convert.ToInt32(current.Value) >= Convert.ToInt32(param.GetParameter())) newValue = current.Value.ToString(); else newValue = param.GetParameter().ToString(); Console.WriteLine("現在値:{0}、比較値:{1} => {2}を適用", current.Value, param.GetParameter(), newValue); current.Value = newValue; return current; } } public class ActionProcesser { public void DoAction(Func<ActionResult> acumrator, Func<Func<ActionResult>, IActionParameter, Func<ActionResult>> func) { var parameters = new List<IActionParameter>(); parameters.Add(new GenericParameter<int>(10)); parameters.Add(new GenericParameter<int>(20)); parameters.Add(new GenericParameter<int>(30)); parameters.Add(new GenericParameter<int>(40)); parameters.Add(new GenericParameter<int>(50)); parameters.Add(new GenericParameter<int>(60)); parameters.Add(new GenericParameter<int>(70)); parameters.Add(new GenericParameter<int>(80)); parameters.Add(new GenericParameter<int>(90)); parameters.Add(new GenericParameter<int>(100)); /* * 第1引数には、アキュムレーター値を返すFuncデリゲートを指定。 * 第2引数(アキュムレーター関数)には、アキュムレーターと同タイプのFuncを返すデリゲートを指定。 * こうすることで各パラメーターを外出しすることが可能になる。 * * アキュムレーター関数にデリゲートを渡すと即時実行されないようなので、最後に()をつけることでInvokeしている。 */ parameters.Aggregate(acumrator, (a, p) => func(a, p))(); } public void DoConcatString() { /* * アキュムレーターが保持する値をアキュムレーター自身が保持できない(デリゲートだから) * そこで、値保持用のContextクラスを使用することで対応した。 * */ var context = new ActionContext(); Func<ActionResult> acumrator = () => { return context.CurrentValue; }; /* * 実際の処理呼び出し。 * ラムダ式の中で、アキュムレーター関数の実処理を呼んでいる。 * こうすることで実処理のテスト容易になる。 * (これが一番の狙いか?) */ DoAction(acumrator, (a, p) => () => Action.ConcatString(a, p)); } public void DoCheckMaxValue() { var context = new ActionContext(); Func<ActionResult> acumrator = () => { context.CurrentValue.Value = "0"; return context.CurrentValue; }; DoAction(acumrator, (a, p) => () => Action.GetMaxValue(a, p)); } } }
Action.ConcatStringのテストコード。
[TestClass()] public class ActionTest { /// <summary> ///ConcatString のテスト ///</summary> [TestMethod()] public void ConcatStringTest() { Func<ActionResult> action = () => new ActionResult() { Value = "やまだ" }; IActionParameter param = new GenericParameter<string>("たろう"); ActionResult expected = new ActionResult() { Value = "やまだたろう" }; ActionResult actual; actual = LinqSample.Action.ConcatString(action, param); Assert.AreEqual(expected.Value, actual.Value); } /// <summary> ///GetMaxValue のテスト ///</summary> [TestMethod()] public void GetMaxValueTest() { Func<ActionResult> action = () => new ActionResult() { Value = "100" }; IActionParameter param = new GenericParameter<int>(99); ActionResult expected = new ActionResult() { Value = "100" }; ActionResult actual; actual = LinqSample.Action.GetMaxValue(action, param); Assert.AreEqual(expected.Value, actual.Value); } }
Windows端末でIPルーティングさせる
上記ネットワークにおいて、
開発端末(VM)(Win7)からサーバー(VM)(XP)へ接続できるようにネットワーク設定した時のメモ
通信の流れ
開発端末(VM)(Win7) → ルーター → ホスト端末(Win7) → ホスト端末(Vista) → サーバー(VM)(XP)
ルーターのルーティングテーブル設定
ルーターに 192.168.1.0/24 は 192.168.111.104へルーティングする設定を追加する
Windows端末で別ネットワーク間のルーティングを有効にする
以下Webページを参照。これで192.168.111.0と192.168.1.0間のルーティングが行えるようになる。
@IT:Windows TIPS -- Tips:IPルーティングを有効にする方法(レジストリ設定編)
ホスト端末(Win7)のルーティング設定
ルーターに 192.168.1.0/24 は 192.168.1.101へルーティングする設定を追加する
javascriptで再帰処理
こんな感じで書きました。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title>再帰呼び出しサンプル</title> </head> <body> <p id="msg_aisatu1">おはよう</p> <p id="msg_aisatu2">こんにちは</p> <p id="msg_aisatu3">おげんきですか</p> <p id="msg_aisatu4">調子はどうだい?</p> </body> <script type="text/javascript"> var Sample = function(){ var _getUniqId = function(id){ //javascriptはvoid関数が無いため、このように対応した var result = id; var func = function(id, cnt){ var searchId = id + (cnt ? cnt : 1); var tgtEle = document.getElementById(searchId); if(tgtEle !== null) func(id, cnt ? ++cnt : 1); else result = searchId; } func(id); return result; } return{ getUniqId : _getUniqId } }; var obj1 = new Sample(); var result = obj1.getUniqId("msg_aisatu"); //検索結果:msg_aisatu5 console.log("検索結果:" + result); </script> </html>
オブジェクト思考のキモを体感するには
このエントリーを読んで。
突破すると一気に学習が加速する「オブジェクト指向学習の壁」を突破する鍵となる知識を、中学生でも分かるように図解してみた(初学者向け) - @fromdusktildawnの本館
「壁」を突破できたと思ったのは、デコレーターパターンとコマンドパターンを実際に使いこなせる様になった時でしょうか。
対象のエントリーでは、優しく図解していることが逆にややこしくなっている気がする。(矢印大杉)
個人的経験から言うとロギング関係クラスをお題にしてオブジェクト指向を説明すると受け入れてもらえることが多かったです。
たとえば、下記のILoggerを実装するクラスたちは利用方法が統一されているため、実装の詳細関係なくロガーとしては同じように使用することができます。これがポリモーフィズムと呼ばれるものです。また、ILogger型の値として各ロガーを扱うこともできます。
(この話題より前のクラス、オブジェクト、メソッドというのは参考書などを読めば理解できるはず。これが理解できないとお話にならないと言わざる得ない。)
これらをさらに拡張して、ログレベルによるフィルタリングを行うようなデコレーターやスレッドセーフ対応を行うためのデコレーターなどを作ることで
実際に体感できるかなと。
//ロガーインターフェイス interface ILogger { //ログ書き込みをする際に呼び出すメソッド名とパラメーターを定義 void WriteLog(string msg); } //標準出力へログ出力 class ConsoleLogger : ILogger { void WriteLog(string msg){ System.Console.WriteLine(msg); } } //指定ファイルへログ出力 class FileLogger : ILogger { private string filePath; public FileLogger(string filePath){ this.filePath = filePath; } void WriteLog(string msg){ //ファイルをオープンし、そこへ書き込む using(var fs = new FileStream(filePath)){ fs.WriteLine(msg); } } } //複数のロガーをまとめて使用する。 class MultiLogger : ILogger { private List<ILogger> loggers = new List<ILogger>(); public void Add(ILogger logger){ loggers.Add(logger); } void WriteLog(string msg){ for(var i=0;i<loggers.Count;i++){ loggers[i].WriteLine(msg); } } } //使用方法 class Program { static void Main(string[] args){ //ConsoleLoggerもFileLoggerもILoggerの実装クラスなため、ILogger型変数に代入することができる。 //(ただしインターフェイスで定義されている操作のみ呼び出し可能) ILogger logger = new ConsoleLogger(); logger.WriteLog("標準出力へログ出力"); logger = new FileLogger("c:\access.log"); logger.WriteLog("ファイルへログ出力"); //MultiLogger.Addメソッドの引数はILogger型。このインターフェイス実装クラスであれば、 //実装の詳細関係なくロガーとして引き渡すことができる。 MultiLogger multiLogger = new MultiLogger(); multiLogger.Add(new ConsoleLogger()); multiLogger.Add(new FileLogger("c:\access.log")); //ConsoleLogger、FileLoggerに "ログ出力!!!" と出力される。 mlogger.WriteLog("ログ出力!!!"); } }