久しぶりのリリースです。
NuGet Gallery | Packages matching codeer
まあ、表題のもの以外も参照バージョンが変わるので全部更新しているのですがw
ちょっと解説します。
解説用のコードはこちらからダウンロードできます。
何ができるようになったかと言うと・・・
- dynamicを引数にとった時の戻り値対応
- デフォルト以外のドメインへのアタッチ
dynamicを引数にとった時の戻り値対応
ExplicitAppVarと言うクラスを追加しました。
えーとショボイです。単にAppVarをラップしただけです。
なにかというと、dynamicなんですよね。
dynamicの変数を引数に渡すと、戻り値もdynamicになるんですよ。
例えばこんな感じです。
IEnumerable<int> Func(string s) { return new int[0]; } void Test() { dynamic s = "abc"; Func(s).//えー、インテリセンスが効かない }
なんでこんなことになるかというと、dynamicを使うとオーバーロードの解決ができないからです。
//dynamicだったら、どっちかわかんないよね。 IEnumerable<int> Func(string s) { return new int[0]; } int Func(int i) { return i; }
で、Friendlyはdynamicを多用します。そしてFriendlyのコンテキストではdynamicは大抵は対象プロセス内のオブジェクトを指すことが多いです。だからそうでないのがdynamicになると非常に紛らわしいんですよね。
それで、今はないのですが、近いうちにライブラリとしても引数に対象プロセス内のオブジェクトを渡して、戻り値に通常の型を戻すメソッドを追加する予定です。
詳細は確定していませんが、WPFStandardControlsに次のような関数が追加されます。
//イメージ static WPFDependencyObjectCollection ByBinding(this WPFDependencyObjectCollection collection, string path, ExplicitVar dataItem); //こんな感じで使う予定 //ByBindingの戻り値が勝手にdynamicになったら紛らわしいし、インテリセンス効かなくなる _window.VisualTree().ByBinding("Hoge", new ExplicitVar(_window.Dynamic().DataContext)).Identify();
まあ、これ(WPFStandardControls)に機能追加したときにもう少し解説します。
デフォルト以外のドメインへのアタッチ
これは凄いですよ!
デフォルト以外のAppDomainにアタッチできるようになりましたw
>誰得?
Friendlyは通常はデフォルトのAppDomainにアタッチします。
だから、複数ドメイン使っているプロジェクトでは操作できない部分があったんですね。
例えばこんなの。
using System; using System.Windows.Forms; namespace Target { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } //新しいドメインでフォーム起動 static int i = 0; public void StartNewDomain() { AppDomain.CreateDomain("new domain" + i++).DoCallBack(()=>new Form().Show()); } } }
この新しいフォームに対しては内部APIを今まで呼べませんでした。
だってAppDomainが違うんだもの・・・
しかし!
なんとこれも操作できるようにしたのです。
こんな感じ。
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; using Codeer.Friendly.Dynamic; using Codeer.Friendly.Windows; using System.Diagnostics; using System.Windows.Forms; namespace Test { [TestClass] public class AppDomainTest { WindowsAppFriend _app; [TestInitialize] public void TestInitialize() { _app = new WindowsAppFriend(Process.Start("Target.exe")); } [TestCleanup] public void TestCleanup() { Process.GetProcessById(_app.ProcessId).Kill(); } [TestMethod] public void Test() { dynamic form = _app.Type<Application>().OpenForms[0]; //新しいドメイン開始 form.StartNewDomain(); //別のドメインを取得 WindowsAppFriend[] apps = _app.AttachOtherDomains(); Assert.AreEqual(1, apps.Length); Assert.AreEqual("new domain 0", (string)apps[0].Type<AppDomain>().CurrentDomain.FriendlyName); } } }