C# – 如何从外部程序集访问内部类

有一个我不能修改的程序集(供应商提供),它具有返回对象types但实际上是内部types的方法。

如何从我的程序集中访问对象的字段和/或方法?

请记住,我无法修改供应商提供的程序集。

本质上,这是我的:

来自供应商:

internal class InternalClass public string test; end class public class Vendor private InternalClass _internal; public object Tag {get{return _internal;}} end class 

从我的程序集使用供应商组装。

 public class MyClass { public void AccessTest() { Vendor vendor = new Vendor(); object value = vendor.Tag; // Here I want to access InternalClass.test } } 

没有访问types(也没有“InternalsVisibleTo”等),你将不得不使用reflection。 但是更好的问题是:你是否应该访问这些数据? 这不是公共types合同的一部分…在我看来,它似乎被视为一个不透明的对象(为了他们的目的,而不是你的目的)。

您已将其描述为公共实例字段; 通过反思得到这个:

 object obj = ... string value = (string)obj.GetType().GetField("test").GetValue(obj); 

如果它实际上是一个属性(不是字段):

 string value = (string)obj.GetType().GetProperty("test").GetValue(obj,null); 

如果它是非公开的,则需要使用GetField / GetPropertyBindingFlags重载。

重要的是 :小心这样的反思; 实现可能会在下一个版本中改变(破坏你的代码),或者它可能被混淆(破坏你的代码),或者你可能没有足够的“信任”(破坏你的代码)。 你在看这个模式吗?

我只看到一个案例,你可以让你的内部成员接触另一个程序集,这是为了testing的目的。

说有一种方法允许“朋友”程序集访问内部:

在项目的AssemblyInfo.cs文件中,为每个程序集添加一行。

 [assembly: InternalsVisibleTo("name of assembly here")] 

这个信息可以在这里find。

希望这可以帮助。

reflection。

 using System.Reflection; Vendor vendor = new Vendor(); object tag = vendor.Tag; Type tagt = tag.GetType(); FieldInfo field = tagt.GetField("test"); string value = field.GetValue(tag); 

明智地使用力量。 不要忘记错误检查。 🙂

我想争论一点 – 你不能扩充原始程序集 – 使用Mono.Cecil你可以注入[InternalsVisibleTo(...)]到3pty程序集。 请注意,可能会有法律上的影响 – 你搞乱了3空assembly和技术含义 – 如果assembly体有很强的名字,你可能需要去掉它或者用不同的键重新签名。

  Install-Package Mono.Cecil 

代码如下所示:

 static readonly string[] s_toInject = { // alternatively "MyAssembly, PublicKey=0024000004800000... etc." "MyAssembly" }; static void Main(string[] args) { const string THIRD_PARTY_ASSEMBLY_PATH = @"c:\folder\ThirdPartyAssembly.dll"; var parameters = new ReaderParameters(); var asm = ModuleDefinition.ReadModule(INPUT_PATH, parameters); foreach (var toInject in s_toInject) { var ca = new CustomAttribute( asm.Import(typeof(InternalsVisibleToAttribute).GetConstructor(new[] { typeof(string)}))); ca.ConstructorArguments.Add(new CustomAttributeArgument(asm.TypeSystem.String, toInject)); asm.Assembly.CustomAttributes.Add(ca); } asm.Write(@"c:\folder-modified\ThirdPartyAssembly.dll"); // note if the assembly is strongly-signed you need to resign it like // asm.Write(@"c:\folder-modified\ThirdPartyAssembly.dll", new WriterParameters { // StrongNameKeyPair = new StrongNameKeyPair(File.ReadAllBytes(@"c:\MyKey.snk")) // }); } 

那么,你不能。 内部类在组件外部是不可见的,所以没有明确的方式直接访问它–AFAIK当然。 唯一的方法是通过reflection使用运行时后期绑定,然后可以间接调用内部类的方法和属性。