Do Not Resolve Members
When a protection runs, it works on a list of members (types, methods, fields, properties, events, …)
that BitMono already filtered for it, the list you get from Context.Parameters.Members. Members that
shouldn’t be touched (anything marked with [Obfuscation] or [DoNotResolve], and so on) are already
gone, and each one is handed to you as an AsmResolver IMetadataMember.
public List<IMetadataMember> Members { get; }
[DoNotResolve] lets your protection narrow that list further. Say you’re writing a renamer and you
don’t want to rename anything that’s looked up by reflection, you’d never know to keep those names
otherwise. Add the attribute with the right flag and BitMono drops those members before they reach you:
[DoNotResolve(MemberInclusionFlags.Reflection)]
public class MyRenamer : Protection
Combine flags with | to exclude several kinds at once:
[DoNotResolve(MemberInclusionFlags.SpecialRuntime | MemberInclusionFlags.Reflection)]
public class MyRenamer : Protection
The flags
Flag |
Excludes |
|---|---|
|
Members the runtime treats as special: special-named methods/events, |
|
Types and members carrying one of the critical model attributes you list in |
|
Members BitMono sees being accessed by reflection ( |
|
Types (and their members) referenced by compiled WPF XAML (BAML), so renaming or namespace-stripping doesn’t leave the XAML pointing at names that no longer exist and crash on load (#212). |
If you don’t add [DoNotResolve] at all, your protection gets every member in the sorted list.
Iterate the sorted list, not the module
Warning
[DoNotResolve] only filters Context.Parameters.Members. It does not touch
Context.Module, walking the module directly bypasses the sorting entirely.
So this is wrong, it ignores everything BitMono sorted for you:
foreach (var type in Context.Module.GetAllTypes()) // don't
{
}
Iterate Context.Parameters.Members instead and pull out the member kinds you need with OfType<>:
// types
foreach (var type in Context.Parameters.Members.OfType<TypeDefinition>())
{
}
// methods
foreach (var method in Context.Parameters.Members.OfType<MethodDefinition>())
{
}
One catch: the member list is sorted, but the members hanging off a type aren’t. If you grab a type and
then read type.Methods, those methods skipped the filter. Always go through the list for each kind you
touch, rather than reaching into type.Methods, type.Fields, and so on.
The analyzer has your back
You don’t have to keep all this in your head. BitMono ships a small Roslyn analyzer (BITM0001) that
spots Context.Module.GetAllTypes() inside a protection and nudges you toward
Context.Parameters.Members, with a one-click fix to swap it over. It rides along with the
BitMono.Core package, so it lights up in plugin projects too, not just the built-in
protections. If you really do mean to walk the raw module (collecting references and the like), hit
Alt+Enter / Ctrl+. on the warning and suppress it - that’s a normal thing to do, not a hack.