3
votes

I have a project that uses dynamic code generation to create a proxy class. This proxy class makes use of internal classes of the project (so that implementation details are not exposed) and so I use InternalsVisibleTo with the name of my dynamically generated assembly. This worked fine until recently, when my client imposed the requirement that all shipped assemblies be strong-named.

The issue arises because, in order to use InternalsVisibleTo with a strong-named assembly, the assemblies it references must also be strong-named and you must provide a public key. Where I'm getting stuck is how to provide a strong name for the dynamically generated assembly. Here is what I've done so far:

  1. I've created a new key pair for dynamic assemblies, so that the .snk can be shipped with the product (obviously we don't want to ship the .snk being used for signing the rest of the project assemblies.)
  2. I've extracted the PublicKey and updated my InternalsVisibleTo to use the new dynamic PublicKey for dynamically referenced assemblies.
  3. I've attempted to sign the dynamically-generated assemblies like this:

        var name = new AssemblyName("ProxyBuilderAssembly");
        var attributes = new CustomAttributeBuilder[1];
        attributes[0] =
            new CustomAttributeBuilder(typeof(AssemblyKeyFileAttribute).GetConstructor(new[] {typeof(string)}),
                                       new object[] {"Dynamic.snk"});
        _assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, attributes);
        _module = _assembly.DefineDynamicModule("ProxyBuilderAssembly", "ProxyBuilderAssembly.dll");
    

Unfortunately this is not working and I have been having a very hard time finding any documentation on how this should work. Does anybody know how to sign a dynamically generated assembly so that it can be given access via InternalsVisibleTo? I can just make the necessary classes public, but that ends up leaking implementation details that would be better left encapsulated.

1
Exactly what kind of dynamic code generation are you using? Reflection.Emit? CodeDom? Cecil?R. Martinho Fernandes
The generation is via Reflection.Emit.Dan Bryant
Moq does this, you could maybe ask its source code... ;-)Lucero

1 Answers

4
votes

There is a "How to: Use Full Signing to Give a Dynamic Assembly a Strong Name" article on MSDN that shows how to sign assemblies generated with Reflection.Emit.

StrongNameKeyPair kp;
// Getting this from a resource would be a good idea.
using(stream = GetStreamForKeyPair())
{
    kp = new StrongNameKeyPair(fs);
}
AssemblyName an = new AssemblyName();
an.KeyPair = kp;
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);