luca-piccioni / OpenGL.Net

Modern OpenGL bindings for C#.
MIT License
570 stars 109 forks source link

TypeInitializationException when used with Costura.Fody #64

Closed Xyene closed 6 years ago

Xyene commented 7 years ago

Hi,

I'm using OpenGL.Net for an app I'm working on, and would like to embed its dependencies as resources with Costura.Fody to simplify deployment. However, OpenGL.Net fails to initialize a context when it's embedded like this, failing with the following error message:

image

My FodyWeavers.xml file is simple:

<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
  <Costura>
    <IncludeAssemblies>
      OpenGL.Net
      OpenGL.Net.WinForms
    </IncludeAssemblies>
  </Costura>
</Weavers>

I'm using OpenGL.Net and OpenGL.Net.WinForms, both v0.5.2.

The issue appears to be this line, where Assembly.GetAssembly(typeof(Egl)).Location is an empty path when embedded, causing Path.GetDirectoryName to fail with the error above.

Since that code is related to ANGLE stuff, which may be tricky to do nicely when embedded, a simple solution would seem to be to fall back on Directory.GetCurrentDirectory() for assemblyPath, or simply short-circuit that block of code entirely.

I'm not sure which option would be preferred, but I would be happy to submit a PR for whatever should be done (this issue is a bit of a show-stopper for me 😀).

luca-piccioni commented 7 years ago

Correct.

I'm currently working on NET Standards. Since I've almost finished, tonight I'll patch it for your case also.

Xyene commented 7 years ago

Thanks, looking forward to it!

luca-piccioni commented 7 years ago

The current workaround is included in the nuget package. Hope this helps.

Xyene commented 6 years ago

Thanks!

I had a chance to try it out today, and it looks like it's still not working. If I'm not mistaken, GetAssemblyLocation should look more like this:

    protected static string GetAssemblyLocation()
    {
#if   NETSTANDARD1_1
            string assemblyPath = null; // XXX
#elif NETSTANDARD1_4 || NETCORE
            string assemblyPath = Directory.GetCurrentDirectory();
#else
            string assemblyPath = Assembly.GetAssembly(typeof(KhronosApi)).Location;

            if (String.IsNullOrEmpty(assemblyPath))
                assemblyPath = Directory.GetCurrentDirectory();
            else
                assemblyPath = Path.GetDirectoryName(assemblyPath);
#endif
            return (assemblyPath);
    }

...as it was Assembly.Location returning the empty path causing Path.GetDirectoryName to fail.

luca-piccioni commented 6 years ago

Ops. I completely missed it! Sorry. Just fixed.