Search code examples
c#ilpeverify

peverify: Method is not visible?


I'm not sure what I'm doing wrong here. I'm generating a dll that uses code in my current assembly. Here's a simplified version containing only the code that that's causing the issue.

static void Main()
{
    Swift.Init();
}

public static class Swift
{
    public static int GetTypeId(object obj)
    {
            return 0;
    }

    public static void Init()
    {
            var getTypeIdMethod = typeof(Swift).GetMethod("GetTypeId",
                BindingFlags.Public | BindingFlags.Static);

            var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Asm"), AssemblyBuilderAccess.RunAndSave);
            var modBuilder = asmBuilder.DefineDynamicModule("Mod", "SerTest.dll");
            var typeBuilder = modBuilder.DefineType("TEST", TypeAttributes.Public);
            var methodBuilder = typeBuilder.DefineMethod("SWITCH",
                MethodAttributes.Public | MethodAttributes.Static,
                CallingConventions.Standard,
                typeof(void), new Type[] { typeof(Stream), typeof(object) });

            // arg0: Stream, arg1: object
            var il = methodBuilder.GetILGenerator();
            il.DeclareLocal(typeof(int));

            // load and store id
            il.Emit(OpCodes.Ldarg_1);                   // push object
            il.Emit(OpCodes.Call, getTypeIdMethod);     // pop object, pass to GetTypeId, push id
            il.Emit(OpCodes.Stloc_0);                   // pop, store in local
            il.Emit(OpCodes.Ret);

            typeBuilder.CreateType();
            asmBuilder.Save("SerTest.dll");
    }
}

peverify gives:

[IL]: Error: [C:\Users\vexe\Desktop\MyExtensionsAndHelpers\Solution\CustomSerializer\bin\Release\SerTest.dll : TEST::SWITCH][offset 0x00000001] Method is not visible.
1 Error(s) Verifying SerTest.dll

What does this error mean? and what I'm doing wrong?

Thanks!

EDIT:

Here's what the generated method looks like in ildasm:

.method public static void  SWITCH(class [mscorlib]System.IO.Stream A_0,
                                   object A_1) cil managed
{
  // Code size       8 (0x8)
  .maxstack  1
  .locals init (int32 V_0)
  IL_0000:  ldarg.1
  IL_0001:  call       int32 [CustomSerializer]Serializer.Swift::GetTypeId(object)
  IL_0006:  stloc.0
  IL_0007:  ret
} // end of method TEST::SWITCH

Solution

  • "Method is not visible" means the method referenced is not visible to the assembly calling it. If you're not using InternalsVisibleTo (which PEVerify doesn't appear to understand, by the way) or protected internal, that means: the method must be a public method of a visible class, and a visible class is a public class optionally nested in a visible class. If you don't like that recursive definition: it's public all the way down up.

    The code as posted should work (Swift is a non-nested public class and GetTypeId a public method), so the problem is in the code as not posted.