[c#] 외부 어셈블리에서 내부 클래스에 액세스하려면 어떻게해야합니까?

개체 형식을 반환하는 메서드 가 있지만 실제로는 내부 형식 인 수정할 수없는 어셈블리 (공급 업체 제공)가 있습니다 .

어셈블리에서 개체의 필드 및 / 또는 메서드에 액세스하려면 어떻게해야합니까?

공급 업체에서 제공 한 어셈블리는 수정할 수 없습니다.

본질적으로 내가 가진 것은 다음과 같습니다.

공급 업체에서 :

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
  }
}



답변

유형에 대한 액세스가 없으면 ( “InternalsVisibleTo”등이 없음) 리플렉션을 사용해야합니다. 그러나 더 좋은 질문은 이 데이터에 액세스 해야 하는가?입니다. 그것은 공개 유형 계약의 일부가 아닙니다 … 그것은 불투명 한 객체로 취급되도록 의도 된 것처럼 들립니다 (당신의 것이 아니라 그들의 목적을 위해).

공개 인스턴스 필드로 설명했습니다. 반사를 통해 이것을 얻으려면 :

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

실제로 속성 (필드 아님) 인 경우 :

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

비공개 인 경우 / BindingFlags오버로드 를 사용해야합니다 .GetFieldGetProperty

중요한 점 은 다음과 같습니다. 구현은 다음 버전에서 변경 될 수 있습니다 (코드 깨짐) 또는 난독 화 될 수 있거나 (코드 깨짐) “신뢰”가 충분하지 않을 수 있습니다 (코드 깨짐). 패턴을 발견하고 있습니까?


답변

내부 구성원에게 다른 어셈블리에 대한 노출을 허용하고 테스트 목적으로 허용하는 경우는 단 하나뿐입니다.

“친구”어셈블리가 내부에 액세스 할 수 있도록 허용하는 방법이 있다고 말합니다.

프로젝트의 AssemblyInfo.cs 파일에서 각 어셈블리에 대한 줄을 추가합니다.

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

이 정보는 여기에서 확인할 수 있습니다.

도움이 되었기를 바랍니다.


답변

[InternalsVisibleTo(...)]3pty 어셈블리에 주입 할 수있는 Mono.Cecil을 사용하여 원래 어셈블리를 확대 할 수 없다는 한 가지 요점을 주장 하고 싶습니다. 법적 의미가있을 수 있습니다. 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"))
   // });
}


답변

반사.

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

힘을 현명하게 사용하십시오. 오류 확인을 잊지 마십시오. 🙂


답변

글쎄, 당신은 할 수 없습니다. 내부 클래스는 어셈블리 외부에서 볼 수 없으므로 직접 액세스 할 수있는 명시적인 방법은 없습니다. 물론 AFAIK. 유일한 방법은 리플렉션을 통해 런타임 후기 바인딩을 사용하는 것입니다. 그러면 내부 클래스에서 간접적으로 메서드와 속성을 호출 할 수 있습니다.


답변