.NET Core Reflection-ASP.NET Core 3 Razorビュー内のプロパティの参照を見つける方法は?

ドリジン

次のようにIViewLocalizerを使用してローカライズされたリソース持つRazorビューがあります。

@inject  Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer Localizer
...
@Localizer.GetString("Click here to Log in")

(POファイルディクショナリを構築するために)プリコンパイルされたビューからこれらすべての文字列を抽出しようとしているので、ビューに挿入されたIViewLocalizerのすべての参照見つける必要があると思います


var findAll = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic |
                                         BindingFlags.Instance | BindingFlags.Static;
var asm = Assembly.LoadFile("MySite.Web.Views.dll"));
var view = asm.GetType("AspNetCore.Views_Home_Index");
var props = view.GetProperties(findAll).Where(p=>p.PropertyType.FullName == "Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer").ToList();

// I want to find all references that use this this IViewLocalizer Localizer.get()
var getter = props.First().GetGetMethod().MetadataToken; 

// How can I do it?
var allMethods = view.GetMethods(findAll);
foreach(var method in allMethods)
{
    // How can I check my methods for usages of that property getter, and in case get the strings?
}

MethodBase.GetMethodBody()。GetILAsByteArray()を使用するこの回答のコードを使用してみましたが、機能しませんでした。メソッドpublic override Task ExecuteAsync()が非常に短いため、ビューが別の場所にレンダリングされているようです。

そしてさらに、私はゲッターのMetadataTokenを探す必要かどうかわからないんだけど(IViewLocalizerは私の意見に注入)または私はその実装した任意の具体的な方法の使用法を探す必要ならばIViewLocalizer.GetString(string)IViewLocalizer.GetString(string, params object[])

PS:注入されたローカライザーが何らかの命名基準に従っている限り、cshtmlビューで正規表現を使用できることを認識しています。リフレクションソリューションがわからない場合に備えて、プランBです。

ドリジン

ILSpyの助けを借りて(そして後でこの回答これによって確認されました)、非同期メソッド(およびイテレータークラス)がステートマシンを表すネストされたヘルパークラス全体で生成されることを発見しましたこれらのヘルパークラスは、メインタイプのNestedTypesプロパティにあります。

内部型のすべてのメソッドを検索に追加すると、探していたメソッド(IViewLocalizerのゲッター)への複数の呼び出しを見つけることができました。これはうまくいきました:

var allMethods = view.GetMethods(findAll).ToList();
allMethods.AddRange( // also search in methods of nested types
  view.GetNestedTypes(findAll).SelectMany(x => x.GetMethods(findAll)));

foreach(var method in allMethods)
{
    var usages = ((MethodBase)method).GetMethodUsageOffsets(get);
    if (usages.Count() > 0)
        Debug.WriteLine($"{method.ReflectedType.FullName}.{method.Name}");
}

AspNetCore.Views_Home_Index3.ExecuteAsync()で見つかると期待していたすべての呼び出しは、実際には内部タイプのこれらのメソッドに分散されていました。

AspNetCore.Views_Home_Index3+<ExecuteAsync>d__22.MoveNext
AspNetCore.Views_Home_Index3+<<ExecuteAsync>b__22_0>d.MoveNext
AspNetCore.Views_Home_Index3+<<ExecuteAsync>b__22_1>d.MoveNext
AspNetCore.Views_Home_Index3+<<ExecuteAsync>b__22_2>d.MoveNext
AspNetCore.Views_Home_Index3+<<ExecuteAsync>b__22_3>d.MoveNext
AspNetCore.Views_Home_Index3+<<ExecuteAsync>b__22_4>d.MoveNext
AspNetCore.Views_Home_Index3+<<ExecuteAsync>b__22_5>d.MoveNext
AspNetCore.Views_Home_Index3+<<ExecuteAsync>b__22_6>d.MoveNext
... etc... all states from the state machine

Mono.Cecilを使用するとこのGetMethodUsageOffsets 拡張機能も必要ないため、Cecilはバイトコードを簡単に解釈できるため、さらに簡単になりました。

var module = ModuleDefinition.ReadModule(System.IO.Path.Combine(appFolder, "MyApp.Web.Views.dll"));
var type = module.Types.First(x => x.Name.EndsWith("Index3"));
var allInstructions = typeDefinition.Methods
    .Union(typeDefinition.NestedTypes.SelectMany(x => x.Methods))
    .Where(m => m.HasBody)
    .SelectMany(x => x.Body.Instructions).ToList();

var calls = allInstructions.Where(i => i.ToString().Contains(
                "callvirt Microsoft.Extensions.Localization.LocalizedString Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer::GetString(System.String)")).ToList();

foreach (var call in calls) // previous is where string parameter is loaded
   System.Diagnostics.Debug.WriteLine(i.Previous.ToString());

結果:

IL_020a: ldstr "More Options"
IL_0241: ldstr "Add Text"
IL_15c8: ldstr "Reset"
IL_15ff: ldstr "Save Text Box Settings"
IL_0019: ldstr "None"
...etc

2020-09-23の編集:いくつかのメソッドが複数のレベルに分割できることを発見したので、第1レベルのNestedTypesのみを検索することはできません。私は現在(純粋な反射の代わりに)Cecilを使用しているので、これは私の現在のコードです:

// All assemblies that I want to scan
var modules = new List<ModuleDefinition>();
modules.Add(ModuleDefinition.ReadModule(System.IO.Path.Combine(appFolder, "MyProject.Web.Views.dll")));
modules.Add(ModuleDefinition.ReadModule(System.IO.Path.Combine(appFolder, "MyProject.Web.dll")));

// All types in my Assemblies
var allTypes = modules.SelectMany(m => m.Types).ToList();

// Then for each of those types I get all Nested Types:

// Get all nested types
for(int i = 0; I < allTypes.Count(); i++) 
    allTypes.AddRange(allTypes[i].NestedTypes); 

// Get all instructions using Cecil
var allInstructions = allTypes.SelectMany(x => x.Methods)
    .Where(m => m.HasBody)
    .SelectMany(x => x.Body.Instructions).ToList();

var i18nInstructions = allInstructions.Where(i => 
    i.ToString().Contains("GetString(System.String)") 
    || i.ToString().Contains("Microsoft.AspNetCore.Mvc.Localization.HtmlLocalizerExtensions::GetHtml(Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer,System.String)")
    ).ToList();

// This prints all values of "ldstr 'value'" 
// which happen before GetString() or GetHtml()
foreach (var i in i18nInstructions)
    System.Diagnostics.Debug.WriteLine(i.Previous.Operand.ToString());

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

.NET CoreでのReflectionの使用

分類Dev

.NET CoreでのReflectionの使用

分類Dev

.NET CoreとASP.NET Core

分類Dev

Net Core:Entity FrameworkCoreとReflectionの主キーを見つける

分類Dev

Reflection .NET Core Create Lambda Expression

分類Dev

Recursion in ASP.NET Core Razor views

分類Dev

ASP.NET CORE 2.0のFromUri

分類Dev

ASP.NET CoreのPayPal

分類Dev

ASP .Net Core Routingの問題?

分類Dev

ASP.NET CoreのValidateInput(bool)

分類Dev

ASP.NET Core 3.0の.AddMvc()?

分類Dev

JsonIgnore属性は、ASP.NET Core3のプロパティをシリアル化し続けます

分類Dev

cookie .net Core3とAsp.netを共有する

分類Dev

ASP.NET Core ToHtmlString

分類Dev

Cookieless ASP.NET Core

分類Dev

how to integrate ASP.NET Core 2.1 with Vue CLI 3?

分類Dev

how to integrate ASP.NET Core 2.1 with Vue CLI 3?

分類Dev

Asp Net Core 3 Sample with 503 Service Unavailable

分類Dev

ASP.NET Core 3 No Sign-In Manager Is Registered for the Scheme

分類Dev

ASP.NET 5、.NET Core、ASP.NET Core 5の違いは何ですか?

分類Dev

ASP.NET Core3はIAuthorizationPolicyProviderを実装します

分類Dev

ASP.NET Core3でid_tokenを使用する

分類Dev

.NET CoreのSOAP?

分類Dev

Asp.Net Core 2.0のActionFilter内のApplicationUser?

分類Dev

ASP。NET Coreでjqueryを使用する方法

分類Dev

ASP.NET Core API:MySQLの使用方法

分類Dev

ASP.NET Coreで、sqliteの使用方法

分類Dev

Find all specific types, with reflection, in assemblies loaded by the application with .net core

分類Dev

ASP.NET Core 2.0 RazorとAngular / React / etc

Related 関連記事

ホットタグ

アーカイブ