Problem with virtual method

J

Jon Skeet

[Posted and mailed.]

Jon Davis said:
Okay, making it abstract did help me identify that this was an assembly
loading problem. I have fixed the assembly loading problem and the problem
is resolved--the child class is FINALLY being executed, even after reverting
back to virtual (YAAAAY!!).

I still perceive this to be a flaw in the Framework. There should have been
an error output indicating that the assembly did not load correctly. QUITE
UNACCEPTABLE, Microsoft. I wasted at least two weeks on this.

So you now have the same code as you had before, but it's working? That
sounds like it's *more likely* to be either a flaw in your build/deploy
environment, or in VS.NET. It *could* still be a bug in the framework,
but I think it's unlikely. (Just my opinion, of course.)

Do you still have a copy of the dll/exes which didn't work? It could
well be instructive to look at the metadata in there, and compare it
with the working version.
 
J

Jon Davis

From what I could tell, one of two things happened, both of which, I
suppose, is a "framework flaw by design"--that is, my own error because of
some things I didn't know to look for:

1. The child type was null:
BaseObject obj =
Activator.CreateInstance(loadedAssemblies.getChildType()); //
returned null
obj.VirtualMethod(); // executed method from base object because obj is
null

or

2. The DLL was locked by Visual Studio .NET because it was open in my
solution:
BaseObject obj =
Activator.CreateInstance(loadedAssemblies.getChildType()); //
returned a Type, but assembly was locked
obj.VirtualMethod(); // executed method from base object because DLL
from obj is locked

In any case, I knew the DLL was indeed being locked because after making
everything abstract and recompiling, I started monitoring assembly.GetType()
and GetType() was returning null and when I tried GetTypes() I got an error
message.

SOOOOOO ... I suppose the problem was indeed my fault because I used this:

Type t = assem.GetType(clrName);

... instead of ..

Type t = assem.GetType(clrName, true);



Jon
 
J

Jon Skeet

Jon Davis said:
From what I could tell, one of two things happened, both of which, I
suppose, is a "framework flaw by design"--that is, my own error because of
some things I didn't know to look for:

1. The child type was null:
BaseObject obj =
Activator.CreateInstance(loadedAssemblies.getChildType()); //
returned null
obj.VirtualMethod(); // executed method from base object because obj is
null

No - Activator.CreateInstance throws an exception if the parameter is
null, and obj.VirtualMethod() would throw an exception if obj were
null.
2. The DLL was locked by Visual Studio .NET because it was open in my
solution:
BaseObject obj =
Activator.CreateInstance(loadedAssemblies.getChildType()); //
returned a Type, but assembly was locked
obj.VirtualMethod(); // executed method from base object because DLL
from obj is locked

I would have thought it would be more likely that it was using an old
version of the DLL, which didn't override the method. Assemblies being
"in use" when they don't need to be is a problem various people have
reported with VS.NET though.

It sounds like it's the recompiling which was the issue - so if you'd
tried following my advice (first copying the solution) you would have
seen very quickly that it wasn't the code which was at fault, and could
have proceeded from there. Not that you're reading this, in all
probability.
 
J

Jon Davis

Yes, the code is basically unchanged; the things that I changed have been
reverted and all is working fine. The problem is that the assemblies were
not loading correctly. This is definitely a bug in one of Microsoft's
tools--the base class should not have executed upon calling the method of a
child class in an invalid / improperly loaded assembly, rather an execution
engine error should have occurred.

An unidentified, inexplicable execution error *did* occur, however, a few
days ago when I tried calling the method manually from the Type object. That
was certainly better than executing the base object.

Jon
 
J

Jon Skeet

Jon Davis said:
Yes, the code is basically unchanged; the things that I changed have been
reverted and all is working fine. The problem is that the assemblies were
not loading correctly. This is definitely a bug in one of Microsoft's
tools--the base class should not have executed upon calling the method of a
child class in an invalid / improperly loaded assembly, rather an execution
engine error should have occurred.

Are you absolutely sure that it was the *loading* that was flawed
instead of the copying of the assembly in the first place? To me it
sounds more likely that you had an old copy of the assembly where
either the method wasn't virtual in the base class or wasn't overridden
in the derived class, and that copy was (possibly incorrectly) "in
use" so couldn't be overwritten.
An unidentified, inexplicable execution error *did* occur, however, a few
days ago when I tried calling the method manually from the Type object. That
was certainly better than executing the base object.

I'd be interested in knowing exactly what the situation was in that
case, and what the execution error was.
 
D

Dave

If you have a similar problem you can try running fuslogvw.exe. If your
problem is related to the runtime being unable to locate an assembly this
tool may help track down the problem.
 
J

Jon Davis

Ah but it did load an assembly and the assembly's class did inherit my base
object and it recognized my type and loaded it as such, it was just
executing the base instance of a virtual method, so I didn't know whether
this was an assembly loading problem ..

I really don't know what happened, but I do know that if it loaded an
obsolete assembly--something I feared for days, but didn't bother to look
further into it until the problem was found--then that would make a lot of
sense and explain the problem: the obsolete assembly's child class didn't
override the virtual method.

What a nrrrrrd I am ....

Jon
 
J

Jay B. Harlow [MVP - Outlook]

Jon,
That's a good question! I do what you are asking in 3 or 4 projects. I have
yet to see it fail.

Rather than loading the assembly, I normally use Type.GetType to load the
type & assembly at one time. This will either return my type or throw an
exception. I have yet to see it return null.

I then use Activator.CreateInstance to create an instance, of the above
type.

For the Type.GetType method, I pass a string in the form
"mynamespace.mytype, myassembly".

As you may have found there are at least three ways to dynamically create
objects in .NET.

Glad you got it to work!

Hope this helps
Jay
 
G

Guest

-----Original Message-----
Thanks for the feedback, Jay, I'll consider your advice. And thanks for not
beating me over the head like some other people have done in the past for
not doing things their way.

Jon


"Jay B. Harlow [MVP - Outlook]"
Jon,
Go the other direction!

Start a new solution with two projects. The first project loads the second
project and calls the virtual method. Include the
minimalist amount of
code
to demonstrate the feature. Does it work?

Start adding features from your larger project, until this new project
fails. Baby steps! Add things one at a time. Hopefully
when you added X,
it
fails, then you know to look at X in the larger project.

This helps solves two problems.
1. It gives you a reference point to compare to the larger project.
2. It proves what you are attempting to do works, or doesn't work. Without
being bothered by the shear volume of the rest of your main project.

3. It also provides a small project that fails, which
is what Jon Skeet
was
asking for.

Hope this helps
Jay

open source and as
such project nor link to it,
it
code until the
problem
project because there are
far I know without
posting
of rewriting code
from
negate the usefulness of
this Please put your tired
self the relevant lines of
code not visually
evaluating is only possible if
you
know how to reproduce
the help me drill down
to without a full
reproduction, problem, I will have
to what I've done, until
I
reproduceable). But
that
complete example
which
gradually (a copy of
the
actually have shown you
the
however, you would then
have me by reproducing
sample
repeated the same
error after copying the
full
that it still didn't
work.
down to the problem,
and

.
 

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