Bug: handling value class events from another assembly

E

Edward Diener

This has occurred in MC++, but since there is very little response on that
NG, I am also reporting it here in the hope that someone can find me a
workaround, and report it to MS.

If a __value class with an event is put into an assembly and a __gc class in
another assembly, which has an instance of the __value class as a data
member, attempts to attach its own event handler to the __value class's
event, everything compiles correctly but the Linker puts out error "LINK :
error LNK2020: unresolved token (0A000003) AValueClassEvent" followed by
"LINK : fatal
error LNK1120: 1 unresolved externals". If the __value class is in the same
assembly as the __gc class, everything is fine and there is no linker error.
What follows is code illustrating this bug.

------------------------------------------------------------------------

In one assembly:

// ValueClass.h
#pragma once
namespace ValueClass
{
public __value class AValueClass
{
public:
AValueClass();
__event System::EventHandler * AValueClassEvent;
int AnInt;
};
}

// ValueClass.cpp
#include "stdafx.h"
#include "ValueClass.h"
ValueClass::AValueClass::AValueClass() : AnInt(1) {}

In a second assembly which references the first assembly:

// HandleValueClassEvent.h
#pragma once
namespace HandleValueClassEvent
{
public __value class AnotherValueClass
{
public:
AnotherValueClass();
__event System::EventHandler * AnotherValueClassEvent;
int AnotherInt;
};
public __gc class HandleEvent
{
public:
HandleEvent();
void AMemberFunction();
void AnotherMemberFunction();
private:
ValueClass::AValueClass avc;
HandleValueClassEvent::AnotherValueClass anvc;
void AnEventHandler(System::Object *,System::EventArgs *);
};
}

// HandleValueClassEvent.cpp
#include "stdafx.h"
#include "HandleValueClassEvent.h"
HandleValueClassEvent::HandleEvent::HandleEvent() {}
void HandleValueClassEvent::HandleEvent::AMemberFunction()
{
avc.AValueClassEvent += new System::EventHandler(this,AnEventHandler);
}
void HandleValueClassEvent::HandleEvent::AnotherMemberFunction()
{
anvc.AnotherValueClassEvent += new
System::EventHandler(this,AnEventHandler);
}
void HandleValueClassEvent::HandleEvent::AnEventHandler(System::Object *
sender,System::EventArgs * e) {}
HandleValueClassEvent::AnotherValueClass::AnotherValueClass() :
AnotherInt(1) {}

----------------------------------------------------------------------------
--

The attempt to add an event handler to avc.AValueClassEvent, which is in
another assembly, causes the linker error. If you comment it out there is no
error. The attempt to add an event handler to anvc.AnotherValueClassEvent,
which is the same assembly, causes no error.

Since I have designed a number of __value classes in an assembly which have
events which must be caught by __gc classes in other assemblies, I badly
need a workaround to this problem else I have to scrapped my own logical
design or duplicate value classes under slightly different names in each
assembly in which I want to use them, which is a real PITA.
 
J

Jon Skeet [C# MVP]

Edward Diener said:
This has occurred in MC++, but since there is very little response on that
NG, I am also reporting it here in the hope that someone can find me a
workaround, and report it to MS.

<snip>

Eek. Unfortunately I'm far from familiar with MC++. It looks like a
bug, certainly, but I'm not sure why.

If the class with the event is a __gc class, does it work? (Not trying
to find a solution here, just the boundaries of a problem.) I would
imagine it does, because otherwise all the events in Windows Forms
would fail.

Have you looked at the assembly containing the event with ildasm? It
might be instructive to see what it's got in it...
 
E

Edward Diener

Jon said:

You found it.
Eek. Unfortunately I'm far from familiar with MC++. It looks like a
bug, certainly, but I'm not sure why.

If the class with the event is a __gc class, does it work?

Yes, of course.
(Not trying
to find a solution here, just the boundaries of a problem.) I would
imagine it does, because otherwise all the events in Windows Forms
would fail.
Yes,


Have you looked at the assembly containing the event with ildasm? It
might be instructive to see what it's got in it...

I will look at it.
 
J

Jon Skeet [C# MVP]

Edward Diener said:
You found it.

Yup :)
I will look at it.

I'll try converting your code into C# and see whether it works then.
The next step (if it does) is to see whether your C++ calling code
links against my C# DLL, and then if my C# calling code works against
your C++ DLL, if you see what I mean.
 
E

Edward Diener

Jon said:
Yup :)


I'll try converting your code into C# and see whether it works then.
The next step (if it does) is to see whether your C++ calling code
links against my C# DLL, and then if my C# calling code works against
your C++ DLL, if you see what I mean.

I know C# also so I can try it myself. I have just been lazy. I will try to
narrow down in what intra-language situations it is occurring. It obviously
still needs to be reported to MS, and I will need to try to find a congenial
workaround for the problem.

I would be really surprised if I am the first to encounter it. A very common
idiom in my RAD programming is to have a component with an embedded __value
class in it as a property. When the component's properties get shown at
design time, the embedded __value class's properties also get expanded. In
this way one can group a component's properties into sub-components,
although a __value class is really not a component. In order for the
component to track the changes to the embedded __value class's properties, I
add events to the __value class for which the component adds handlers, in
order for the component to know when one of the embedded properties
changes.

Perhaps I am the only .NET programmer using the common idiom above who has
ever put their __value classes in one assembly and their components using
the __value classes in another assembly. Yet again this is very common when
the __value classes are shared by more than one assembly. So it is odd that
no one would have found this bug before.

The workaround in this case, of course, is to duplicate the __value classes
under a slightly different name in each assembly. That is a pretty awful
kludge of a clean design. I am really hoping to avoid that.
 
E

Edward Diener

Jon said:
Yup :)


I'll try converting your code into C# and see whether it works then.
The next step (if it does) is to see whether your C++ calling code
links against my C# DLL, and then if my C# calling code works against
your C++ DLL, if you see what I mean.

I have investigated this bug and here is what I found:

1) Whether one creates the assembly, with the value class having an event,
in C++ or C# the testing result is the same. The one thing I noticed that
was different in the generated assembly, using .NET Reflector, is that the
C++ version generates a raise_AValueClassEvent while the C# version does
not. Still one can trigger the value class event from within either assembly
without any errors.

2) If one creates another assembly in C#, which embeds the value class in
the first assembly and hooks up an event handler to the event in the value
class, there are no linker error, whether one uses the C++ or C# version of
the first assembly.

3) If one creates another assembly in C+, which embeds the value class in
the first assembly and hooks up an event handler to the event in the value
class, the linker error occurs whether one uses the C++ or C# version of the
first assembly.

I have a solution which shows all this pretty obviously. I will report this
to MS by phone on Monday or Tuesday to see if I can get a decent workaround.
I will also report the minor enumeration bug which I found using C++ (
enumeration in one assembly, when referred to in another assembly, needs
full name with enumeration name and not just enumerated value ).

I do wish that MS would put out fixes to VS .NET problems and not wait until
Whidbey and saddle programmers with another full year at least of
workarounds to bugs, such as this one. The arrogance of their refusal to
consider service packs for VS .NET is awful. It was bad enough when Borland
refused to fix bugs in BCB with a sort of demented obstinancy, but when MS,
who had been consistent in providing bug fixes to their previous VS6
product, does it, it is even worse. Despite what they think, programmers
will remember the way they have been treated by large corporations.
 

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