개체 형식을 반환하는 메서드 가 있지만 실제로는 내부 형식 인 수정할 수없는 어셈블리 (공급 업체 제공)가 있습니다 .
어셈블리에서 개체의 필드 및 / 또는 메서드에 액세스하려면 어떻게해야합니까?
공급 업체에서 제공 한 어셈블리는 수정할 수 없습니다.
본질적으로 내가 가진 것은 다음과 같습니다.
공급 업체에서 :
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
오버로드 를 사용해야합니다 .GetField
GetProperty
중요한 점 은 다음과 같습니다. 구현은 다음 버전에서 변경 될 수 있습니다 (코드 깨짐) 또는 난독 화 될 수 있거나 (코드 깨짐) “신뢰”가 충분하지 않을 수 있습니다 (코드 깨짐). 패턴을 발견하고 있습니까?
답변
내부 구성원에게 다른 어셈블리에 대한 노출을 허용하고 테스트 목적으로 허용하는 경우는 단 하나뿐입니다.
“친구”어셈블리가 내부에 액세스 할 수 있도록 허용하는 방법이 있다고 말합니다.
프로젝트의 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. 유일한 방법은 리플렉션을 통해 런타임 후기 바인딩을 사용하는 것입니다. 그러면 내부 클래스에서 간접적으로 메서드와 속성을 호출 할 수 있습니다.