Como acessar a class interna de assembly externo

Ter um assembly que não posso modificar (fornecido pelo fornecedor) que tenha um método retornando um tipo de object, mas na verdade é de um tipo interno.

Como posso acessar os campos e / ou methods do object da minha assembly?

Lembre-se de que não posso modificar o assembly fornecido pelo fornecedor.

Em essência, aqui está o que eu tenho:

Do fornecedor:

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

Da minha assembly usando o assembly do fornecedor.

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

Sem access ao tipo (e sem “InternalsVisibleTo” etc) você teria que usar reflection. Mas uma pergunta melhor seria: você deveria estar acessando esses dados? Não faz parte do contrato de tipo público … parece-me que se destina a ser tratado como um object opaco (para os seus propósitos, não o seu).

Você descreveu isso como um campo de instância pública; para obter isso via reflection:

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

Se for realmente uma propriedade (não um campo):

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

Se não for público, você precisará usar a sobrecarga BindingFlags de GetField / GetProperty .

Importante aparte : tenha cuidado com reflexões como essa; a implementação pode mudar na próxima versão (quebrar seu código), ou pode ser ofuscada (quebrar seu código), ou você pode não ter “confiança” suficiente (quebrando seu código). Você está manchando o padrão?

Vejo apenas um caso em que você permitiria a exposição a seus membros internos para outra assembly e isso é para fins de teste.

Dizendo que existe uma maneira de permitir que o access de conjuntos “Amigos” aos internos:

No arquivo AssemblyInfo.cs do projeto, você adiciona uma linha para cada assembly.

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

esta informação está disponível aqui.

Espero que isto ajude.

Reflexão.

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

Use o poder com sabedoria. Não se esqueça da verificação de erros. 🙂

Eu gostaria de argumentar um ponto – que você não pode aumentar a assembly original – usando Mono.Cecil você pode injetar [InternalsVisibleTo(...)] na assembly 3pty. Note que pode haver implicações legais – você está mexendo com a assembly do 3pty e as implicações técnicas – se o assembly tiver um nome forte, você precisará retirá-lo ou assiná-lo novamente com uma chave diferente.

  Install-Package Mono.Cecil 

E o código como:

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

Bem, você não pode. Classes internas não podem ser visíveis fora de sua assembly, portanto, nenhuma maneira explícita de acessá-las diretamente – AFAIK, é claro. A única maneira é usar a binding tardia de tempo de execução via reflection, então você pode invocar methods e propriedades da class interna indiretamente.