# Reflection Problems

# Why renaming obfuscation breaks code that uses reflection

When you turn on the Obfuscation option, every type, method, property, field, event, parameter, and namespace can be renamed to meaningless identifiers. While this thwarts casual IL inspection, it introduces runtime failures anywhere your program expects the original metadata names to exist.

Typical patterns that fail are:

Reflection scenario What happens after renaming?
Type.GetType("MyApp.Services.EmailService") or Assembly.GetType(...) The string literal no longer matches the obfuscated type name, so null is returned. Subsequent calls throw NullReferenceException or TypeLoadException.
Activator.CreateInstance("MyApp", "EmailService") Same as above.
typeof(Foo).GetMethod("SendEmail") or LINQ-to-Entities mapping strings The member is now a, b, … so reflection cannot locate the method or property.
nameof(SomeProperty) persisted to config, JSON, or XAML At compile time nameof still gives the pre-obfuscated text. After deployment the runtime knows only the scrambled name.
Custom attributes that embed names (e.g., [Route("api/Users/{userId}")]) and are inspected at runtime Framework looks for a method called GetUsers but finds c.

In short, any string-based reference to metadata breaks once those identifiers are no longer the same.


# Fixing it with System.Reflection.ObfuscationAttribute

.NET ships an attribute that .NET Reactor understands: System.Reflection.ObfuscationAttribute.
You decorate exactly the types or members that must stay intact.

# Common attribute properties

Property Meaning
Exclude = true (default) Do not obfuscate this item.
ApplyToMembers = true Extend the rule to all nested members (methods, properties, fields) of the attributed type.
StripAfterObfuscation = true (default) Remove the attribute itself from the final assembly so attackers don’t see your rules.

# At the class level – exclude a whole type (and its members)

using System.Reflection;

namespace MyApp.Services
{
    [Obfuscation(ApplyToMembers = true)]
    internal class EmailService
    {
        public void SendEmail(string to, string subject) { … }
    }
}

EmailService and everything inside it remain exactly as compiled (EmailService, SendEmail, subject, …).

# At the method or property level – fine-grained control

internal class ReportBuilder
{
    // Only this method keeps its name; the rest of the class can be renamed.
    [Obfuscation()]
    public string BuildFromTemplate(string templateName) { … }
}

# Practical checklist

  • Audit reflection usage — Search for .GetType(..), Activator.CreateInstance(..), GetMethod(..), nameof(..), [Route(..)], resource look-ups, XAML bindings, etc.
  • Categorize — Decide whether to allow renaming and patch code (e.g., use typeof(T) instead of strings) or keep original names.
  • Annotate — Add ObfuscationAttribute where keeping names is simpler than refactoring.
  • Automated test pass — Run integration tests against the obfuscated build—reflection issues often surface immediately as TypeLoadException or binding errors.

By explicitly marking only the reflection-critical hotspots with ObfuscationAttribute, you get the best of both worlds: robust runtime behavior and maximum symbol scrambling everywhere else.

# WPF and XAML bindings

WPF and other XAML-based UI code can depend on names that are resolved at runtime rather than by normal compiled references. A binding such as Path=CustomerName, a command name, a converter type loaded by name, or configuration that names a view or view model can stop resolving if the corresponding symbol is renamed.

When a protected WPF application loses bindings or UI behavior after enabling obfuscation:

  1. Confirm that the unprotected build and the protected build with renaming disabled both work.
  2. Identify properties, commands, types, or members referenced by XAML, binding paths, resources, configuration, or runtime lookup strings.
  3. Preserve only those required names with ObfuscationAttribute, Declarative Protection, or an Advanced Rule.
  4. Test the final protected application with the same XAML, resource dictionaries, themes, and view models used in production.

Do not exclude the whole application from renaming unless a narrower rule is impractical. Dynamic XAML or third-party UI frameworks can introduce additional name-based contracts, so integration tests against the protected output are important.

# Related topics

Advanced Rules Editor, Declarative Protection

JSON serialization · WPF and XAML bindings · Protect a library