Type.GetType()在跨程序集反射时返回null的解决方法

本文介绍了在.NET开发中,如何正确地实现跨程序集的反射操作。文章详细解释了使用typeof与Type.GetType的区别,并提供了具体的代码示例来指导开发者如何避免运行时错误。

在开发中,经常会遇到这种情况,在程序集A.dll中需要反射程序集B.dll中的类型。如果使用稍有不慎,就会产生运行时错误。例如使用Type.GetType("BNameSpace.ClassName")在程序集A.dll获取程序集B.dll中的类型,就会返回Null。

关于跨程序集的反射,有两点需要注意:

 

1、如果使用typeof,编译能通过,则跨程序集的反射一定可以正常运行。可以说,typeof是支持强类型的。比如

1  Type supType  =   typeof (BNameSpace.SubSpace.Class);

如果当前程序集没有添加对EnterpriseServerBase.dll的引用,则编译会报错。

 

2、如果使用Type.GetType来进行反射的话,情况就复杂些。这是因为Type.GetType是非强类型的。Type.GetType的参数是一个string为类型的完全限定名,如果当string表示的目标类型不在当前程序集中,则运行时Type.GetType会返回null。解决的办法是:首先加载目标程序集,然后再使用Assembly.GetType方法来获取类型。如

1  Assembly asmb  =  Assembly.LoadFrom( " EnterpriseServerBase.dll " ) ;
2  Type supType  =  asmb.GetType( " EnterpriseServerBase.DataAccess.IDBAccesser " ) ;

 

注意,当使用Type.GetType的时候,即使你添加了对EnterpriseServerBase.dll的引用,Type.GetType("EnterpriseServerBase.DataAccess.IDBAccesser")也会返回null,这是因为Type.GetType只会在当前程序集中进行类型搜索!

using System; using System.Collections.Generic; using System.Windows.Forms; using System.Text; namespace NetObfuscator { public class MainForm : Form { private TextBox txtInputAssembly; private TextBox txtOutputAssembly; private Button btnBrowseInput; private Button btnBrowseOutput; private Button btnObfuscate; private CheckBox chkRenameMembers; private CheckBox chkEncryptStrings; private CheckBox chkControlFlow; private Label label1; private Label label2; public MainForm() { InitializeComponent(); } private void InitializeComponent() { // 初始化所有控件 this.txtInputAssembly = new TextBox(); this.txtOutputAssembly = new TextBox(); this.btnBrowseInput = new Button(); this.btnBrowseOutput = new Button(); this.btnObfuscate = new Button(); this.chkRenameMembers = new CheckBox(); this.chkEncryptStrings = new CheckBox(); this.chkControlFlow = new CheckBox(); this.label1 = new Label(); this.label2 = new Label(); // 设置窗体属性 this.Text = ".NET混淆工具"; this.ClientSize = new System.Drawing.Size(534, 201); // 设置控件位置和属性 // txtInputAssembly this.txtInputAssembly.Location = new System.Drawing.Point(120, 20); this.txtInputAssembly.Size = new System.Drawing.Size(300, 20); // txtOutputAssembly this.txtOutputAssembly.Location = new System.Drawing.Point(120, 50); this.txtOutputAssembly.Size = new System.Drawing.Size(300, 20); // btnBrowseInput this.btnBrowseInput.Location = new System.Drawing.Point(430, 18); this.btnBrowseInput.Size = new System.Drawing.Size(75, 23); this.btnBrowseInput.Text = "浏览..."; this.btnBrowseInput.Click += new EventHandler(this.btnBrowseInput_Click); // btnBrowseOutput this.btnBrowseOutput.Location = new System.Drawing.Point(430, 48); this.btnBrowseOutput.Size = new System.Drawing.Size(75, 23); this.btnBrowseOutput.Text = "浏览..."; this.btnBrowseOutput.Click += new EventHandler(this.btnBrowseOutput_Click); // btnObfuscate this.btnObfuscate.Location = new System.Drawing.Point(220, 150); this.btnObfuscate.Size = new System.Drawing.Size(100, 30); this.btnObfuscate.Text = "开始混淆"; this.btnObfuscate.Click += new EventHandler(this.btnObfuscate_Click); // chkRenameMembers this.chkRenameMembers.Location = new System.Drawing.Point(120, 80); this.chkRenameMembers.Text = "重命名成员"; this.chkRenameMembers.AutoSize = true; // chkEncryptStrings this.chkEncryptStrings.Location = new System.Drawing.Point(120, 100); this.chkEncryptStrings.Text = "加密字符串"; this.chkEncryptStrings.AutoSize = true; // chkControlFlow this.chkControlFlow.Location = new System.Drawing.Point(120, 120); this.chkControlFlow.Text = "混淆控制流"; this.chkControlFlow.AutoSize = true; // label1 this.label1.Location = new System.Drawing.Point(20, 23); this.label1.Text = "输入程序集:"; this.label1.AutoSize = true; // label2 this.label2.Location = new System.Drawing.Point(20, 53); this.label2.Text = "输出程序集:"; this.label2.AutoSize = true; // 添加控件到窗体 this.Controls.Add(this.txtInputAssembly); this.Controls.Add(this.txtOutputAssembly); this.Controls.Add(this.btnBrowseInput); this.Controls.Add(this.btnBrowseOutput); this.Controls.Add(this.btnObfuscate); this.Controls.Add(this.chkRenameMembers); this.Controls.Add(this.chkEncryptStrings); this.Controls.Add(this.chkControlFlow); this.Controls.Add(this.label1); this.Controls.Add(this.label2); } private void btnBrowseInput_Click(object sender, EventArgs e) { using (OpenFileDialog openFileDialog = new OpenFileDialog()) { openFileDialog.Filter = "NET Assemblies|*.exe;*.dll"; if (openFileDialog.ShowDialog() == DialogResult.OK) { txtInputAssembly.Text = openFileDialog.FileName; } } } private void btnBrowseOutput_Click(object sender, EventArgs e) { using (SaveFileDialog saveFileDialog = new SaveFileDialog()) { saveFileDialog.Filter = "NET Assemblies|*.exe;*.dll"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { txtOutputAssembly.Text = saveFileDialog.FileName; } } } private void btnObfuscate_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtInputAssembly.Text) || string.IsNullOrEmpty(txtOutputAssembly.Text)) { MessageBox.Show("请选择输入和输出程序集路径"); return; } try { // 检查是否安装了Mono.Cecil if (!IsMonoCecilAvailable()) { MessageBox.Show("请先安装Mono.Cecil NuGet包"); return; } // 读取程序集 var assembly = ReadAssembly(txtInputAssembly.Text); if (assembly == null) { MessageBox.Show("无法读取程序集,请确保已安装Mono.Cecil"); return; } // 应用选择的混淆技术 if (chkRenameMembers.Checked) RenameMembers(assembly); if (chkEncryptStrings.Checked) EncryptStrings(assembly); if (chkControlFlow.Checked) ObfuscateControlFlow(assembly); // 保存混淆后的程序集 WriteAssembly(assembly, txtOutputAssembly.Text); MessageBox.Show("混淆完成!"); } catch (Exception ex) { MessageBox.Show($"混淆过程中出错: {ex.Message}"); } } private bool IsMonoCecilAvailable() { try { // 尝试加载Mono.Cecil类型 var type = Type.GetType("Mono.Cecil.AssemblyDefinition, Mono.Cecil"); return type != null; } catch { return false; } } private object ReadAssembly(string path) { try { // 使用反射调用Mono.Cecil,避免编译依赖 var assemblyDefinitionType = Type.GetType("Mono.Cecil.AssemblyDefinition, Mono.Cecil"); var readAssemblyMethod = assemblyDefinitionType.GetMethod("ReadAssembly", new[] { typeof(string) }); return readAssemblyMethod.Invoke(null, new object[] { path }); } catch { return null; } } private void WriteAssembly(object assembly, string path) { try { // 使用反射调用Mono.Cecil的Write方法 var writeMethod = assembly.GetType().GetMethod("Write", new[] { typeof(string) }); writeMethod.Invoke(assembly, new object[] { path }); } catch (Exception ex) { MessageBox.Show($"保存程序集出错: {ex.Message}"); } } private void RenameMembers(object assembly) { try { // 使用反射访问Mono.Cecil对象 var modulesProperty = assembly.GetType().GetProperty("Modules"); var modules = modulesProperty.GetValue(assembly) as IEnumerable<object>; foreach (var module in modules) { var typesProperty = module.GetType().GetProperty("Types"); var types = typesProperty.GetValue(module) as IEnumerable<object>; foreach (var type in types) { // 重命名类型 var isPublicProperty = type.GetType().GetProperty("IsPublic"); var isNestedPublicProperty = type.GetType().GetProperty("IsNestedPublic"); var nameProperty = type.GetType().GetProperty("Name"); bool isPublic = (bool)isPublicProperty.GetValue(type); bool isNestedPublic = (bool)isNestedPublicProperty.GetValue(type); if (!isPublic && !isNestedPublic) nameProperty.SetValue(type, GenerateRandomName()); // 重命名方法 var methodsProperty = type.GetType().GetProperty("Methods"); var methods = methodsProperty.GetValue(type) as IEnumerable<object>; foreach (var method in methods) { var methodIsPublicProperty = method.GetType().GetProperty("IsPublic"); var methodIsFamilyProperty = method.GetType().GetProperty("IsFamily"); var methodIsFamilyOrAssemblyProperty = method.GetType().GetProperty("IsFamilyOrAssembly"); var methodNameProperty = method.GetType().GetProperty("Name"); bool methodIsPublic = (bool)methodIsPublicProperty.GetValue(method); bool methodIsFamily = (bool)methodIsFamilyProperty.GetValue(method); bool methodIsFamilyOrAssembly = (bool)methodIsFamilyOrAssemblyProperty.GetValue(method); if (!methodIsPublic && !methodIsFamily && !methodIsFamilyOrAssembly) methodNameProperty.SetValue(method, GenerateRandomName()); } // 重命名字段 var fieldsProperty = type.GetType().GetProperty("Fields"); var fields = fieldsProperty.GetValue(type) as IEnumerable<object>; foreach (var field in fields) { var fieldIsPublicProperty = field.GetType().GetProperty("IsPublic"); var fieldNameProperty = field.GetType().GetProperty("Name"); bool fieldIsPublic = (bool)fieldIsPublicProperty.GetValue(field); if (!fieldIsPublic) fieldNameProperty.SetValue(field, GenerateRandomName()); } } } } catch (Exception ex) { MessageBox.Show($"重命名成员出错: {ex.Message}"); } } private void EncryptStrings(object assembly) { try { // 使用反射访问Mono.Cecil对象 var modulesProperty = assembly.GetType().GetProperty("Modules"); var modules = modulesProperty.GetValue(assembly) as IEnumerable<object>; foreach (var module in modules) { var typesProperty = module.GetType().GetProperty("Types"); var types = typesProperty.GetValue(module) as IEnumerable<object>; foreach (var type in types) { var methodsProperty = type.GetType().GetProperty("Methods"); var methods = methodsProperty.GetValue(type) as IEnumerable<object>; foreach (var method in methods) { var hasBodyProperty = method.GetType().GetProperty("HasBody"); bool hasBody = (bool)hasBodyProperty.GetValue(method); if (hasBody) { var bodyProperty = method.GetType().GetProperty("Body"); var body = bodyProperty.GetValue(method); var getILProcessorMethod = body.GetType().GetMethod("GetILProcessor"); var processor = getILProcessorMethod.Invoke(body, null); var instructionsProperty = body.GetType().GetProperty("Instructions"); var instructions = instructionsProperty.GetValue(body) as IList<object>; var opCodesType = Type.GetType("Mono.Cecil.Cil.OpCodes, Mono.Cecil"); var ldstrField = opCodesType.GetField("Ldstr"); var ldstrOpCode = ldstrField.GetValue(null); for (int i = 0; i < instructions.Count; i++) { var opCodeProperty = instructions[i].GetType().GetProperty("OpCode"); var opCode = opCodeProperty.GetValue(instructions[i]); if (opCode.Equals(ldstrOpCode)) { var operandProperty = instructions[i].GetType().GetProperty("Operand"); string originalString = (string)operandProperty.GetValue(instructions[i]); string encryptedString = EncryptString(originalString); // 插入解密方法调用 operandProperty.SetValue(instructions[i], encryptedString); // 创建调用指令 var callOpCodeField = opCodesType.GetField("Call"); var callOpCode = callOpCodeField.GetValue(null); var instructionType = Type.GetType("Mono.Cecil.Cil.Instruction, Mono.Cecil"); var createMethod = instructionType.GetMethod("Create", new[] { Type.GetType("Mono.Cecil.Cil.OpCode, Mono.Cecil"), typeof(System.Reflection.MethodInfo) }); var decryptMethod = typeof(StringDecryptor).GetMethod("Decrypt"); var callInstruction = createMethod.Invoke(null, new object[] { callOpCode, decryptMethod }); var insertAfterMethod = processor.GetType().GetMethod("InsertAfter", new[] { instructionType, instructionType }); insertAfterMethod.Invoke(processor, new object[] { instructions[i], callInstruction }); } } } } } } } catch (Exception ex) { MessageBox.Show($"加密字符串出错: {ex.Message}"); } } private void ObfuscateControlFlow(object assembly) { try { // 使用反射访问Mono.Cecil对象 var modulesProperty = assembly.GetType().GetProperty("Modules"); var modules = modulesProperty.GetValue(assembly) as IEnumerable<object>; foreach (var module in modules) { var typesProperty = module.GetType().GetProperty("Types"); var types = typesProperty.GetValue(module) as IEnumerable<object>; foreach (var type in types) { var methodsProperty = type.GetType().GetProperty("Methods"); var methods = methodsProperty.GetValue(type) as IEnumerable<object>; foreach (var method in methods) { var hasBodyProperty = method.GetType().GetProperty("HasBody"); bool hasBody = (bool)hasBodyProperty.GetValue(method); if (hasBody) { var bodyProperty = method.GetType().GetProperty("Body"); var body = bodyProperty.GetValue(method); var getILProcessorMethod = body.GetType().GetMethod("GetILProcessor"); var processor = getILProcessorMethod.Invoke(body, null); var instructionsProperty = body.GetType().GetProperty("Instructions"); var instructions = instructionsProperty.GetValue(body) as IList<object>; // 简单的控制流混淆 - 插入无意义的分支 var opCodesType = Type.GetType("Mono.Cecil.Cil.OpCodes, Mono.Cecil"); var br_sField = opCodesType.GetField("Br_S"); var br_sOpCode = br_sField.GetValue(null); var instructionType = Type.GetType("Mono.Cecil.Cil.Instruction, Mono.Cecil"); var createMethod = instructionType.GetMethod("Create", new[] { Type.GetType("Mono.Cecil.Cil.OpCode, Mono.Cecil"), instructionType }); for (int i = 0; i < instructions.Count - 1; i += 3) { var jumpTarget = instructions[i + 2]; var branchInstruction = createMethod.Invoke(null, new object[] { br_sOpCode, jumpTarget }); var insertBeforeMethod = processor.GetType().GetMethod("InsertBefore", new[] { instructionType, instructionType }); insertBeforeMethod.Invoke(processor, new object[] { instructions[i + 1], branchInstruction }); } } } } } } catch (Exception ex) { MessageBox.Show($"混淆控制流出错: {ex.Message}"); } } private string GenerateRandomName() { // 生成随机名称 const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; var random = new Random(); var length = random.Next(5, 15); var name = new char[length]; for (int i = 0; i < length; i++) { name[i] = chars[random.Next(chars.Length)]; } return new string(name); } private string EncryptString(string input) { // 简单的字符串加密 byte[] inputBytes = Encoding.UTF8.GetBytes(input); for (int i = 0; i < inputBytes.Length; i++) { inputBytes[i] = (byte)(inputBytes[i] ^ 0xAA); } return Convert.ToBase64String(inputBytes); } } // 字符串解密类 public static class StringDecryptor { public static string Decrypt(string encrypted) { byte[] encryptedBytes = Convert.FromBase64String(encrypted); for (int i = 0; i < encryptedBytes.Length; i++) { encryptedBytes[i] = (byte)(encryptedBytes[i] ^ 0xAA); } return Encoding.UTF8.GetString(encryptedBytes); } } } CS1061“MainForm”未包含”Form1_Load”的定义,并且找不到可接受第一个“MainForm”类型参数的可访问扩展方法“Form1_Load”(是否缺少using 指令或程序集引用?) CS0121以下方法或属性之间的调用具有二义性:“MainForm.InitializeComponent()和MainForm.InitializeComponent() CS0111类型“MainForm”已定义了一个名为“InitializeComponent”的具有相同参数类型的成员 CS0260类型“MainForm”的声明上缺少partial修饰符;存在此类型的其他分部声明
09-18
在C#中反射程序集将依赖程序集一起加载,可采用以下方法: ### 使用`Assembly.LoadFrom`方法 `Assembly.LoadFrom`会自动加载目标程序集所引用和依赖的其他程序集。示例代码如下: ```csharp using System; using System.Reflection; class Program { static void Main() { try { // 使用 LoadFrom 加载程序集,会自动加载依赖 Assembly assembly = Assembly.LoadFrom("YourAssembly.dll"); // 后续操作,例如获取类型、调用方法Type type = assembly.GetType("YourNamespace.YourClass"); if (type != null) { object instance = Activator.CreateInstance(type); // 调用方法等操作 } } catch (Exception ex) { Console.WriteLine($"加载程序集出错: {ex.Message}"); } } } ``` ### 处理`AssemblyResolve`事件 当程序集加载失败,`AssemblyResolve`事件会被触发,可以在该事件处理程序中手动加载依赖程序集。示例代码如下: ```csharp using System; using System.IO; using System.Reflection; class Program { static void Main() { AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; try { // 使用 LoadFile 加载主程序集 Assembly mainAssembly = Assembly.LoadFile("YourMainAssembly.dll"); // 后续操作 } catch (Exception ex) { Console.WriteLine($"加载程序集出错: {ex.Message}"); } } private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { // 获取依赖程序集的名称 string assemblyName = new AssemblyName(args.Name).Name; // 假设依赖程序集和主程序集在同一目录 string assemblyPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), $"{assemblyName}.dll"); if (File.Exists(assemblyPath)) { // 手动加载依赖程序集 return Assembly.LoadFrom(assemblyPath); } return null; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值