Reflection allows applications to locate and instantiate types or invoke members at runtime. Because these references may not be visible during static analysis, Dotfuscator cannot always determine which identifiers must remain unchanged.
When reflection is used to reference types or members by name, you may need to create renaming exclusions to preserve application behavior.
When Exclusions Are Required
If a type or member name is determined dynamically, for example, from a configuration file, user input, or another runtime source, Dotfuscator cannot identify it during analysis.
For example, consider the following (C#) code fragment:
public object GetNewType() {
Type type = Type.GetType( GetUserInputString(), true );
object newInstance = Activator.CreateInstance( type );
return newInstance;
} This code loads a type by name and dynamically instantiates it. In addition, the name is coming from a string input by the user. There is no way for Dotfuscator to predict which type names the user eventually enters.
In this case, you need to configure Dotfuscator to exclude the names of all potentially loadable types. You can still allow renaming of methods and fields.
Reduce the Scope of Exclusions
If reflection is limited to a known set of types, exclude only those types instead of entire assemblies.
Consider the following (C#) code fragment:
public MyInterface GetNewType() {
Type type = Type.GetType( GetUserInputString(), true );
object newInstance = Activator.CreateInstance( type );
return newInstance as MyInterface;
} In this case, it is immediately obvious that only a subset of types need to be excluded: those implementing MyInterface.
Best Practices
- Exclude only the types that are accessed dynamically.
- Continue allowing members to be renamed whenever possible.
- Test applications that use reflection after protection.
- Review Smart Obfuscation warnings for additional guidance.
Related Articles