13 Março, 2013 0 Comentários AUTOR: elemarjr CATEGORIAS: Sem categoria Etiquetas:

Isole "InternalsVisibleTo" em um arquivo

Tempo de leitura: 1 minuto

Olá. Tudo certo?

Você conhece o atributo de assembly InternalsVisibleTo? Ele faz com que classes/métodos/propriedades marcados como internal sejam "vistos" nos assemblies que indicados. É um recurso importante utilizado com frequência quando precisamos escrever, por exemplo, testes de unidade para esses membros.

Inicialmente, costumava adicionar esse atributo no arquivo AssemblyInfo.cs. Entretanto, inspecionando o código fonte de alguns projetos open source, percebi que é comum criar um arquivo "InternalsVisibleTo.cs" para este fim.

Abaixo. reprodução parcial desse arquivo no fonte do Rx (encurtei os nomes dos assemblies intencionalmente).

// Copyright (c) Microsoft Open Technologies, Inc.
// All rights reserved. See License.txt in the project root for license information.

using System;

#if SIGNED

#if SIGNENHANCED // Key 272 for .NET 4.5 and beyond
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Debugger, [..]")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Experimental, [..]")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Linq, [..]")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.PlatformServices, [..]")]
#else            // Key 35 for older platforms
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Debugger, [..]")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Experimental, [..]")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Linq, [..]")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.PlatformServices, [..]")]
#endif

#else

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Debugger")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Experimental")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Linq")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.PlatformServices")]

#endif

Perceba que o time do Rx utiliza "InternalsVisibleTo" com outras finalidades além de facilitar testes.

Agora, o mesmo conceito aplicado no projeto do EntityFramework (novamente, encurtei os nomes dos assemblies).

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

#if !INTERNALS_INVISIBLE

using System.Runtime.CompilerServices;

[assembly:
    InternalsVisibleTo(
        "EntityFramework.UnitTests, [..]")]
[assembly:
    InternalsVisibleTo(
        "EntityFramework.FunctionalTests.Transitional, [..]")]

// for Moq

[assembly:
    InternalsVisibleTo(
        "DynamicProxyGenAssembly2, [..]"
        )]

#endif

O que você acha?

Era isso.

0 Comentários

  1. Alberto Chvaicer 3 anos ago says:

    Perfeito!
    Procurava por essa solução hà tempos.

    Cheguei a criar testes no mesmo assembly por não saber isso!

    Responder
  2. O que acha de separar o arquivo?

    Cara se for isso não vi benefício algum, pode ser limitação minha, mas não vi razão para tirar do AssemblyInfo.

    Responder
  3. Robson Castilho 3 anos ago says:

    No meu caso, como estou expondo apenas para 1 assembly (que é o projeto de testes correspondente ao projeto testado), nunca vi necessidade.
    Fica no AssemblyInfo mesmo! 🙂

    Responder
  4. http://rafaelromao.com 3 anos ago says:

    Também costumo manter o uso do atributo InternalsVisibleTo em um arquivo separado. A principal vantagem que tenho com isso é poder compartilhar o arquivo (Add as a link) em diferentes projetos de uma mesma solução. Nesse caso os Internals de todos os projetos onde esse arquivo é adicionado tornam-se visíveis aos assemblies listados (como parâmetro para o atributo).

    Responder
  5. Thiago Andrade 3 anos ago says:

    Onde é definido SIGNENHANCED? (Mostrado no código do artigo)
    Já vem definido no próprio Visual Studio ou temos que definir na mão?

    Solução muito boa.

    Responder