1

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
vexe
  • 5,433
  • 12
  • 52
  • 81
  • Is the assembly you're generating this code from accessible to PEVerify when you're running it? That is, is "CustomSerializer.dll/exe" in the same directory or the GAC? – Jeroen Mostert Feb 19 '15 at 13:33
  • @JeroenMostert CustomSerializer.exe and SerTest.dll are in the same directory yes. – vexe Feb 19 '15 at 15:53
  • Also, just checked the C# code in ILSpy, it didn't throw any errors when viewing the class (sometimes it does if the code was invalid) and displayed the correct code: "int typeId = Swift.GetTypeId(obj);" – vexe Feb 19 '15 at 15:54
  • 1
    The only way I can reproduce this error is if the method `Swift.GetTypeId` is indeed not public (because `Swift` is nested in a non-public type, for example). But this doesn't appear to be the case in the IL you posted. – Jeroen Mostert Feb 19 '15 at 16:00
  • Silly me! Could have sworn I checked it to make sure the method was public. Convert to answer if you want. – vexe Feb 19 '15 at 16:10

1 Answers1

2

"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.

Jeroen Mostert
  • 27,176
  • 2
  • 52
  • 85