"Object does not match target type." using dynamic compiling & inv

G

Guest

Howdy!

I posted this question on CSharpCorner.com, but then realized I should
probably post it on a more active newsgroup. This will be my only cross-post.

I'm creating a game engine, and using CodeDOM for my scripting needs (I
realize I could use yacc or something else, but I wanted to try using CodeDOM
-- this is more of an exercise for me to learn this stuff).

Well, I compile my in-game scripts just fine. See appendix A for my code
that does that (it was too cluttered to paste right here. Suffice to say, it
works)

I'm referencing my own executable, so that I can share code/types from my
main application.

Now, I go over and try to invoke the method from the assembly I just
compiled. The code that tries that looks like this:

object retObj = null;
object[] scriptParams = new object[1];
scriptParams[0] = context; // "context" is of type miteScriptContext, which
is what the method is expecting
retObj = script.ScriptMethod.Invoke(script.asm, scriptParams);


However, it throws the following error for me:

"Unhandled Exception: System.Reflection.TargetException: Object does not
match target type."

So I'm thinking, "okay, I must be having a wrong parameter", but I checked
and double-checked and my code seems correct. *FINALLY* I wrote the following
debug code:

object[] scriptParams = new object[1];
scriptParams[0] = context;

Console.WriteLine("Method return type is: " +
script.ScriptMethod.ReturnType.ToString());
Console.WriteLine("Passing in...");
Console.WriteLine(scriptParams[0].GetType().ToString() + ": " +
scriptParams[0].GetHashCode().ToString());
Console.WriteLine(scriptParams[0].GetType().Assembly.Location);
Console.WriteLine(scriptParams[0].GetType().Assembly.FullName);
Console.WriteLine();
Console.WriteLine("...into...");
Console.WriteLine(script.ScriptMethod.GetParameters()[0].ParameterType.ToString()
+ ": " +
script.ScriptMethod.GetParameters()[0].ParameterType.GetHashCode().ToString())
Console.WriteLine(script.ScriptMethod.GetParameters()[0].ParameterType.Assembly.Location)
Console.WriteLine(script.ScriptMethod.GetParameters()[0].ParameterType.Assembly.FullName);
Console.WriteLine();

retObj = script.ScriptMethod.Invoke(script.asm, scriptParams);

That outputs the following...


Method return type is: System.Object
Passing in...
MITE.GameData.Scripting.miteScriptContext: 4
C:\Documents and Settings\cherron\My Documents\SharpDevelop
Projects\MITE\bin\Debug\MITE.exe
MITE, Version=1.0.1986.18485, Culture=neutral, PublicKeyToken=null

....into...
MITE.GameData.Scripting.miteScriptContext: 202521200
C:\Documents and Settings\cherron\My Documents\SharpDevelop
Projects\MITE\bin\Debug\MITE.exe
MITE, Version=1.0.1986.18485, Culture=neutral, PublicKeyToken=null


Okay. That's *REALLY* confusing to me. Basically it's saying that the types
don't match up. I'm passing in an object of type miteScriptContext. Both
types say that they come from the same assembly, from the same version,
everything. However, when referenced in different ways, that type comes up
with different hash codes?

Am I on crack, or is something wrong here? How can it be getting the same
type from the same assembly in two different ways and thinking that they're
different?

If anyone can point me in the right direction, that would be wonderful.

I know this method of calling scripts works, because I have another project
where I'm practicing the same method and it works just fine! I can't figure
out what's different about *this* project that makes it generate different
hash codes for the same type (which effectively makes Reflection think that
they're different types altogether). I would like to post a small sample app,
and if I need to create one, I can, it's just that there's a lot of overhead
involved, and it wouldn't be a very "small" app. :) I was hoping someone
would understand the theory of the way .NET determines if types are
compatible, and could help me out from a theory point of view.

Help, please? :)

Thanks!

Respectfully,
clint


Appendix A: My code to compile an assembly from code at runtime

public static Assembly CompileCode(string code)
{
Microsoft.CSharp.CSharpCodeProvider provider = new
Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.ICodeCompiler compiler = provider.CreateCompiler();
System.CodeDom.Compiler.CompilerParameters param = new
System.CodeDom.Compiler.CompilerParameters();
System.CodeDom.Compiler.CompilerResults results;

param.GenerateInMemory = true;
param.GenerateExecutable = false;
param.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

results = compiler.CompileAssemblyFromSource(param, code);

if (results.Errors.HasErrors)
{
string errText = "";
foreach (System.CodeDom.Compiler.CompilerError err in results.Errors)
{
errText += ("Line [" + err.Line.ToString() + "] :" + err.ErrorText + "\r\n");
}
// TODO: Better error reporting mechanism.
System.Windows.Forms.MessageBox.Show(errText,
results.Errors.Count.ToString() + " errors");
return null;
}

return (results.CompiledAssembly);
}
 
J

Jon Skeet [C# MVP]

Clint Herron said:
I posted this question on CSharpCorner.com, but then realized I should
probably post it on a more active newsgroup. This will be my only cross-post.

I'm creating a game engine, and using CodeDOM for my scripting needs (I
realize I could use yacc or something else, but I wanted to try using CodeDOM
-- this is more of an exercise for me to learn this stuff).

Well, I compile my in-game scripts just fine. See appendix A for my code
that does that (it was too cluttered to paste right here. Suffice to say, it
works)

I'm referencing my own executable, so that I can share code/types from my
main application.

<snip>

Check whether
scriptParams[0].GetType()==
script.ScriptMethod.GetParameters(0).ParameterType

I suspect they won't, even though they're loaded from the same assembly
file. My guess is that you've got two copies of the same assembly in
memory.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that. I know it may be hard, given the other things you
said, but if you can do it, it would be very helpful.
 
G

Guest

Hey Jon! Thanks for your great replies (in this, and in other threads).
Check whether
scriptParams[0].GetType()==
script.ScriptMethod.GetParameters(0).ParameterType

Oh interesting!It shows up as "true".

That was surprising to me -- I would have assumed "false" given everything
else that I'm seeing.

So perhaps it's another object that isn't matching type? Is there any way of
telling what object it's messing up on? It's a horrible error message. I'm
not afraid of digging into the CIL if I'm told what to look for.

Thanks!

Respectfully,
clint
 
J

Jon Skeet [C# MVP]

Clint Herron said:
Hey Jon! Thanks for your great replies (in this, and in other threads).
Check whether
scriptParams[0].GetType()==
script.ScriptMethod.GetParameters(0).ParameterType

Oh interesting!It shows up as "true".

That was surprising to me -- I would have assumed "false" given everything
else that I'm seeing.
Likewise.

So perhaps it's another object that isn't matching type? Is there any way of
telling what object it's messing up on? It's a horrible error message. I'm
not afraid of digging into the CIL if I'm told what to look for.

Have you checked that the target of the call (i.e. the object you're
calling the method *on*) is of the right type?
 
G

Guest

Oh my goodness, I'm so schtupid.

I was passing in the assembly, rather than an instance of the class inside
the assembly.

Wow, thankyou. You were a huge help!!!

Here is output, showing the compiled "get" script in action:
get flask
You try to pick up the flask, but fail. A strange voice booms. 'That feature
is
not yet implemented.'


Thanks again Jon! Is there anything I can do to vote for you or boost your
rating in any way? You've been incredibly helpful. Thanks!

--clint

Jon Skeet said:
Clint Herron said:
Hey Jon! Thanks for your great replies (in this, and in other threads).
Check whether
scriptParams[0].GetType()==
script.ScriptMethod.GetParameters(0).ParameterType

Oh interesting!It shows up as "true".

That was surprising to me -- I would have assumed "false" given everything
else that I'm seeing.
Likewise.

So perhaps it's another object that isn't matching type? Is there any way of
telling what object it's messing up on? It's a horrible error message. I'm
not afraid of digging into the CIL if I'm told what to look for.

Have you checked that the target of the call (i.e. the object you're
calling the method *on*) is of the right type?
 
J

Jon Skeet [C# MVP]

Clint Herron said:
Oh my goodness, I'm so schtupid.

I was passing in the assembly, rather than an instance of the class inside
the assembly.

Goodo :)
Wow, thankyou. You were a huge help!!!

Here is output, showing the compiled "get" script in action:

get flask
You try to pick up the flask, but fail. A strange voice booms. 'That feature
is
not yet implemented.'

LOL :) That takes me back to the days when I was porting Colossal Cave
to run on WAP phones.
Thanks again Jon! Is there anything I can do to vote for you or boost your
rating in any way? You've been incredibly helpful. Thanks!

Just your thanks are more than enough :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top