Jump to content
  • Advertisement
Sign in to follow this  
Sijmen

[.net] TypeLoadException?

This topic is 5390 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there, I'm writing this little helper tool that should be able to load an assembly and run every class that implements the IExecModule interface, which has methods such as Init() and Run(). Now, I wrote a test that does, besides other things, load a bitmap font using my own bitmap font class. This class is located within ManagedGL, my library. There is also the FontMode enummeration:
public enum FontMode
{
	Ascii,
	NeHestyle
}
/edit: why does the forum keep making the s of NeHestyle lowercase? This assembly is properly referenced, and when I look in the bin directory of the bigger project, the ManagedGL file is there. And when I open that ManagedGL.dll file there, it does contain the FontMode enum. But then, when I use the testbed, open the dll, and run, I a TypeLoadException at ButtonLabelText.Init() - this function initializes the test - about not being able to load the FontMode type from ManagedGL. I confirmed that it is there in the assembly. These are the methods from the testbed that loads/runs the assembly:
Type[] getTypes(Assembly assembly)
{
	Type[]    types = assembly.GetTypes();
	ArrayList ret   = new ArrayList();
	
	foreach(Type type in types)
	{
		if(type.GetInterface(typeof(IExecModule).FullName)!=null)
			ret.Add(type);
	}
	
	return (Type[])ret.ToArray(typeof(Type));
}

void loadFile(string filename)
{			
	assembly = Assembly.LoadFile(filename);
	modules  = getTypes(assembly);
	
	if(modules.Length<1)
	{
		MessageBox.Show("There were no valid classes found.", "Error", 
			MessageBoxButtons.OK, MessageBoxIcon.Error);
		return;
	}
	
	modules = getTypes(assembly);
	
	list.Items.Clear();
	foreach(Type type in modules)
		list.Items.Add(type);
	
	fileBox.Text = filename;
}

private void run_Click(object sender, System.EventArgs e)
{
	Type type = (Type)list.SelectedItem;
	currentInstance = (IExecModule)assembly.CreateInstance(type.FullName);
	
	try
	{
		SurfaceWindow screen = new SurfaceWindow(new Size((int)screenSizeW.Value,
			(int)screenSizeH.Value), (int)depth.Value, fullscreen.Checked);
		screen.Quit += new QuitEventHandler(screen_Quit);
		
		currentInstance.Init(screen, new Hashtable());
		currentInstance.Run();
	}
	catch(Exception ex)
	{
		MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK,
			MessageBoxIcon.Error);
	}
	finally
	{
		currentInstance.Dispose();
		Surface.DisposeAll();
	}
}

What could I be doing wrong? [Edited by - Sijmen on October 11, 2004 11:57:46 PM]

Share this post


Link to post
Share on other sites
Advertisement
If you are only going to do a for each on your array list in getTypes anyway, you'ld be better off just returning an IEnumerable - that way you are achieving genericity without duplicating effort. Remember this isn't C++ - you can pass around references and trust the GC - you don't need to deep copy stuff unless it's going to be changed from the original in someway.

The problem with your enumeration comes from MSDN:

The following additional restrictions apply to enumerations:

They cannot define their own methods.
They cannot implement interfaces.
They cannot define properties or events.


Note the interfaces bit - and how you are loading stuff from the module. This means they are stuck with the interfaces as defined by the parent System.Enum class:

public abstract class Enum : IComparable, IFormattable, IConvertible

I'm not sure what an IExecModule is - doesn't seem to be a built in type. Also consider use of "as" instead of casting in some instances... as "as" doesn't throw exceptions if a cast cannot succeed - it only returns null.

Good luck!

Paul

Share this post


Link to post
Share on other sites
IExecModule is an interface that is implemented by all classes that can be run as 'game module', such as the intro, menu system, and the in-game module.

How is my FontType enum used wrong? The FontType enum is only used here (in the class that I try to run from the testbed - this is IExecModule.Init()):


public void Init(SurfaceWindow screen, Hashtable data)
{
this.screen = screen;

Surface fontSurface = new Surface("data/Font.bmp");
fontSurface.ColorKey = Color.Black;
fontSurface.ColorKeyed = true;
BinaryReader reader = new BinaryReader(new FileStream("data/Font.dat", FileMode.Open));
int[] widths = new int[256];
for(int i=0; i<widths.Length; i++)
reader.ReadByte();
reader.Close();
font = new BitmapFont(fontSurface, FontMode.Ascii, widths);
}





The crash seems to happen here (last line within the method). The reference to ManagedGL.dll is set, ManagedGL.Extended (which contains the enum) is 'using'-ed, and the ManagedGL.dll file is up to date and contains the enum.

*Sijmen is confused :S

/edit
Uhm.. I posted the enum declaration, do I do anything wrong there?

Share this post


Link to post
Share on other sites
It's got nothing to do with what paulecoyote said since the FontEnum is automatically being loaded from ManagedGL.dll.

However, not sure what the problem is :(

You're using other types from ManagedGL (I presume Surface and SurfaceWindow are in ManagedGL), so the problem isn't that the assembly can't be loaded. You're not dynamically loading the assembly and it's compiling so it must be finding the FontEnum type fine. That only leaves you with the obscure description 'cannot load the type' from MSDN.

Sorry, I wasn't really much help.....

Hmm, try dynamically loading ManagedGL.dll and getting the FontEnum type manually and see what that does.

Share this post


Link to post
Share on other sites
Sounds difficult. Maybe I should try this first: I almost forgot that the ManagedGL lib is accomplished by another project, the benchmarker. I could see if fonts work in there (they are already used). Just a sec...

/edit
That's weird. The benchmarker works ok, with fonts and all.

Share this post


Link to post
Share on other sites
You don't have a FontEnum defined in your testbed under the same namespace as ManagedGL do you? I doubt you do, but I'm short on ideas.

The only other thing I can suggest is check that the copy of ManagedGL.dll in your testbed's bin directory is the most recent version, but from the sounds of things you've already checked that.

Share this post


Link to post
Share on other sites
I removed the ManagedGL.dll file and rebuilt the project, and confirmed (with the #d assembly scout) that the enum is there. I am using the ManagedGL namespace, and well, that's about it right?

Where can I look next, if I can't find the solution here? Any other newsgroup/forum? The programming teachers tell me that calling the base of an overriden method is impossible, so I can't really depend on them.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sijmen
I removed the ManagedGL.dll file and rebuilt the project, and confirmed (with the #d assembly scout) that the enum is there. I am using the ManagedGL namespace, and well, that's about it right?

Have you made sure the copy in your testbed's bin directory is up to date? (that is, if the ManagedGL's project's bin directory is different to that of the testbed's project)

Quote:
Where can I look next, if I can't find the solution here? Any other newsgroup/forum?

Try the message boards at GotDotNet.

Quote:
The programming teachers tell me that calling the base of an overriden method is impossible, so I can't really depend on them.

Well in the case of interfaces they're kinda right since an interface can't have any base implementation to call, although it sounds like they were saying in general which is obviously wrong. Your teachers suck [smile]

Share this post


Link to post
Share on other sites
Quote:
Have you made sure the copy in your testbed's bin directory is up to date? (that is, if the ManagedGL's project's bin directory is different to that of the testbed's project)


The ManagedGL.dll file in the bin directory in which the test dll file is located contains the definition for the enum, so yes, it's up to date.

Quote:
Try the message boards at GotDotNet.


Thanks, I'll ask there.

Quote:

Well in the case of interfaces they're kinda right since an interface can't have any base implementation to call, although it sounds like they were saying in general which is obviously wrong. Your teachers suck [smile]


Well, actually I was porting some simple schoolwork (a crossroad 'simulation') from java/awt to .NET/GDI+ for fun, and he told me I wouldn't succeed in porting the class structure since only Java has those features and .NET doesn't... :S

btw, thats a ++ for you!

Share this post


Link to post
Share on other sites
Quote:
Original post by joanusdmentia
It's got nothing to do with what paulecoyote said since the FontEnum is automatically being loaded from ManagedGL.dll.

...

Hmm, try dynamically loading ManagedGL.dll and getting the FontEnum type manually and see what that does.


...

Well if he's loading all types that ONLY implement this interface IExecModule in while interating through the Assembly:

if(type.GetInterface(typeof(IExecModule).FullName)!=null)

... and enum FontMode CANNOT possibly implement IExecModule, because no enums can implement extra interfaces, then how is that type being loaded?!

EDIT: Anyway, you may want to try LoadFrom rather then LoadFile - LoadFrom is to be used for loading files you want to execute from, LoadFile is for examination really and doesn't check dependencies.

[Edited by - paulecoyote on October 12, 2004 6:26:28 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!