Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从外部程序集访问内部类?_C#_Class - Fatal编程技术网

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

C# 如何从外部程序集访问内部类?,c#,class,C#,Class,具有我无法修改的程序集(供应商提供),该程序集的方法返回对象类型,但实际上是内部类型 如何从程序集中访问对象的字段和/或方法 请记住,我无法修改供应商提供的程序集 public class MyClass { public void AccessTest() { Vendor vendor = new Vendor(); object value = vendor.Tag; // Here I want to access InternalClass.test

具有我无法修改的程序集(供应商提供),该程序集的方法返回对象类型,但实际上是内部类型

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

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

public class MyClass
{
  public void AccessTest()
  {
    Vendor vendor = new Vendor();
    object value = vendor.Tag;
    // Here I want to access InternalClass.test
  }
}
[assembly: InternalsVisibleTo("name of assembly here")]
本质上,我拥有的是:

来自供应商:

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
  }
}
[assembly: InternalsVisibleTo("name of assembly here")]

如果无法访问该类型(并且没有“InternalsVisibleTo”等),则必须使用反射。但更好的问题是:您是否应该访问这些数据?它不是公共类型合同的一部分。。。对我来说,这听起来像是要被当作一个不透明的物体来对待(出于他们的目的,而不是你的目的)

您已经将其描述为公共实例字段;要通过反射获取此信息,请执行以下操作:

object obj = ...
string value = (string)obj.GetType().GetField("test").GetValue(obj);
如果它实际上是一个属性(不是字段):

如果它是非公共的,则需要使用
GetField
/
GetProperty
BindingFlags
重载


重要的旁白:小心这样的思考;实现可能会在下一个版本中更改(破坏代码),也可能会混淆(破坏代码),或者您可能没有足够的“信任”(破坏代码)。你发现模式了吗?

嗯,你不能。内部类在其程序集之外不可见,因此没有直接访问它的显式方法——当然是AFAIK。 唯一的方法是通过反射使用运行时后期绑定,然后您可以从内部类间接调用方法和属性。

反射

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);

明智地使用权力。不要忘记错误检查。:)

我只看到一种情况,您允许将内部成员暴露于另一个程序集,这是出于测试目的

表示有一种方法允许“友元”程序集访问内部:

在项目的AssemblyInfo.cs文件中,为每个部件添加一行

public class MyClass
{
  public void AccessTest()
  {
    Vendor vendor = new Vendor();
    object value = vendor.Tag;
    // Here I want to access InternalClass.test
  }
}
[assembly: InternalsVisibleTo("name of assembly here")]
此信息可用


希望这能有所帮助。

我想提出一点——您不能扩充原始程序集——使用Mono.Cecil,您可以将
[InternalsVisibleTo(…)]
注入3pty程序集。请注意,可能存在法律问题-您正在处理3pty程序集和技术问题-如果程序集具有强名称,您需要将其剥离或使用不同的密钥重新签名

 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"))
   // });
}

你可以使用reflectionMarc调用任何东西,我想知道……可以访问私有字段/属性,但是有没有办法使用正确的类型强制转换GetValue返回的对象?@GiovanniCampo,如果你静态地知道类型是什么:当然-只需强制转换即可。如果您不知道静态的类型,那么我们甚至不清楚这意味着什么,对于那些将内容发布为内部构件(实际上是公共API的一部分)的人来说,这意味着什么?或者他们使用了
InternalsVisibleTo
,但没有包含您的程序集?如果这个符号不是真正隐藏的,它就是ABI的一部分。对我来说,不能修改意味着它来自一个nuget,我不想通过修改创建和管理一个本地nuget。此外,对一些人来说,失去一个强有力的名字也很重要。但这是一个有趣的观点。扩展到测试目的的情况。在不同上下文中耦合内部构件的任何场景。例如,在Unity中,您可能有一个运行时程序集、一个测试程序集和一个编辑器程序集。运行时内部应该对测试和编辑器程序集可见。我认为这个答案没有帮助-OP说他不能修改供应商的程序集,这个答案涉及修改供应商项目的AssemblyInfo.cs文件