VSTS拡張の話はまだ続きますが、今日困ったことが解決したのでネタにしました。
Plugin的な機構を実現したくて、Assembly.LoadFrom
でDLLを読み込んでいる箇所があるのですが、読み込んだDLLの先で呼び出しているライブラリ(実際にはNewtonsoft.Json
)のバージョンが本体より古いため、AssemblyBindingを設定する必要がありました。
Web.config に指定しても働いてくれなくてなんでだと思っていたらこの記事を見つけました。
Redirecting Assembly Loads at Runtime – SLaks.Blog
この記事にすべて書いてあるのですが、AppDomain.CurrentDomain.AssemblyResolve
イベントハンドラを記述することで、ハンドラの中で読み込む対象のDLLを変更することができる、というものになります。今回使うことになった、Newtonsoft.Json
の場合のコードがこうなります。
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { //本体が参照しているNewtonsoft.Jsonのバージョンを指定する var targetVersion = new Version(7, 0, 0, 0); var publicKeyToken = "30ad4fe6b2a6aeed"; var requestedAssembly = new AssemblyName(args.Name); if (requestedAssembly.Name != "Newtonsoft.Json") return null; Debug.WriteLine("Redirecting assembly load of " + args.Name + ",\tloaded by " + (args.RequestingAssembly?.FullName ?? "(unknown)")); requestedAssembly.Version = targetVersion; requestedAssembly.SetPublicKeyToken(new AssemblyName("x, PublicKeyToken=" + publicKeyToken).GetPublicKeyToken()); requestedAssembly.CultureInfo = CultureInfo.InvariantCulture; return Assembly.Load(requestedAssembly); };
Newtonsoft.Json
が読み込もうとされたら、バージョン固定でリダイレクトしています。当然本体が参照しているバージョンと違うと無限Loadが試みられるので注意が必要です*1。また、当然本体が参照するバージョンが替われば書き換える必要があります。実運用考えるともう少し工夫の余地はありますが、とりあえず回避策ということで紹介しました。
*1:そのため参照先のサイトではイベントハンドラを解除している