Where's the bug?

Where's the bug?

Old forum URL: forums.lhotka.net/forums/t/226.aspx


xal posted on Tuesday, May 30, 2006

Hi all. I'm here asking about the most challenging question I ever asked.
I have created a very small solution that serves as an example of my current set up.

Basically it contains:

ClassLibrary1:
-ISavable: Interface that contains just a Save() method
-BaseForm:
    It's a form with a generic definition "T" (with an ActiveBusinessBase restriction).
    It contains a protected member of type T named "obj"
    It has a Method named TryAndSave that does this: "obj = obj.Save()"
    It Implements ISavable.Save (Which calls TryAndSave())
   
ClassLibrary2:
-Class1: It inherits from ActiveBusinessBase
-DerivedForm:
    It inherits from BaseForm(Of Class1).
    It has a method named DoTheSameThingTheBaseDoes() that only does this: "obj = obj.Save()" (exactly like TryAndSave)


Now, I have a Winforms project. It contains an mdi form with 2 buttons.
The project makes an instance of Derived form and stores a reference to the form as ISavable.
The first Button calls the instance's (stored as Isavable) save method.
The second button casts the instance to DerivedForm and calls DoTheSameThingTheBaseDoes()
   
If you click the first button, the app will throw a TypeLoadException with a message similar to this:
    Could not load type 'Csla.BusinessBase`1' from assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
If you click the second button, all is well.
   
   
If you go to the BaseForm Class and change it's restriction to BusinessBase, then both buttons work just fine.

Now, I'm sorry, but i need to say: WTF!?!?
Can anybody find a reasonable explanaiton for this?

I'm attaching the sample project for your own amusement.
It includes references so that you don't have to get everything compiled.
This costed me nearly 2 days of work.

PLEASE, PLEASE, PLEASE, some one tell me what the problem is.

Andrés

Note: I had to remove the references from the zip because of size restrictions for attachments.
You can get the compiled references from here:
http://xal.hopto.org/CSLA20.zip
It includes CSLA ActiveObjects and Observer.

miroslav replied on Tuesday, May 30, 2006

That's a very strange bug you got there.
I've downloaded your code and tried to figure out what's causing the exception. I've set a breakpoint on the TryAndSave() method call:

    Public Sub save() Implements ISavable.save
        TryAndSave()
    End Sub


After selecting Debug -> Step Into, the exception happens immediately. Execution cannot even enter into the TryAndSave method.

I think that something inside ActiveObjects.dll is causing the exception (probeably the ActiveObjects.Core.DataPortal.Update() method). Why don't you try to remove all the references to the ActiveObjects.dll from your solution, add ActiveObjects project (source code) to the solution and reference it in the other projects. Maybe you would get a more meaningful exception then.

Miroslav

xal replied on Tuesday, May 30, 2006

Hi Miroslav!

Thanks for answering.

Yes, I've noticed what you say, and in fact if you change the save() method, to do "obj = obj.Save()" directlly instead of calling TryAndSave, then it will fail before entering the save method.

I will try what you say, there's nothing to loose, but if there is a problem in AO, then why does the method in the derived form work?

I'm beginning to think that there is a problem with the generics implementation, as unlikely as it seems...

In fact, if you change the code in the TryAndSave method to something like the example below, it does work:

dim x as ActiveObjects.IEditableBusinessObject

x = DirectCast(obj, ActiveObjects.IEditableBusinessObject)

obj= DirectCast(x.SaveObject, T)

 

What troubles me the most is that the code is very simple and there seems to be nothing wrong with it.

For now, I've managed to work around the issue by declaring my real form like this:

Public Class BaseForm(Of T as {BusinessBase(Of T), IObservable, IEditableBusinessObject})

But still, I wonder what could be wrong, and why is it looking for BusinessBase(Of ) inside ClassLibrary2?

Really interesting case. Maybe we need to contact someone at redmond that can shed some light into this matter... Ideas anyone?

Andrés

xal replied on Wednesday, May 31, 2006

I just added the ActiveObjects project to the solution and the problem remains exactly as before.

On a side note, in my previous post I said it was looking for BusinessBase(Of ) inside ClassLibrary2, but I meant ClassLibrary1, sorry. Also, the exception doesn't actually say "BusinessBase(Of )", it says "Csla.BusinessBase`1". Again, sorry for the lack of precision, I was away from my computer and my memory cheated me. Embarrassed [:$]


Andrés

ajj3085 replied on Wednesday, May 31, 2006

Sorry if this is a silly question; does ClassLibrary1 have a reference to Csla?

If you're still stuck, try getting .Net Reflector (http://www.aisto.com/roeder/dotnet/) and examining all the compiled binaries in your bin folder.  Write down all the references and make sure the version numbers are all in sycn.

i've seen this if Lib3 depends on 1.0.0.0 of Lib1, and Lib2 depends on 1.2.0.0 of Lib1.

Andy

xal replied on Wednesday, May 31, 2006

Yes, I use Reflector all the time. All projects have all the references.
Just download the project and see for yourself. The code is extremely simple. I wrote it in less than 5 minutes.
Anyway, for the record, I did check all my references and recompiled everything long before posting this message.
The problem is very weird and it will not be clear to you until you download the project and see what's happening for yourself...

Andrés

ajj3085 replied on Wednesday, May 31, 2006

I don't think I can help... this may be a Vb.Net thing.

I checked with Reflector the binaries in the Windows project.  One thing I notice is that ClassLibrary2 doesn't seem to have a reference to Csla, nor does the Exe file that is generated. 

I have a similar dependency setup, and my libraries and Exe do in fact have a reference to Csla when examined in Reflector.

Of course I use C# exclusively, so I'm not sure if VB will find the dependency by looking in ClassLibrary1.dll.  Is this the norm for Vb.net references?

Andy

RockfordLhotka replied on Wednesday, May 31, 2006

Andy, by the time it is CIL it is not a VB issue - it is just the way the CLR type loader works. If that assembly doesn't reference Csla.dll then boom! The same thing would be true in C#, F#, COBOL.NET or any other language.

xal replied on Wednesday, May 31, 2006

Well, all projects do have references to:
-Csla.dll
-Observer.dll
-ActiveObjects.dll

Rocky, did you take a look at the project? What do you think?

Andrés

xal replied on Wednesday, May 31, 2006

Andy,

You actually gave me some very good food for thought:

The project does have the reference, but the compiler (or vs, I'm not sure) seems to think that the reference is not being used.
I changed the code inside TryAndSave to this:

obj = DirectCast(obj, BusinessBase(Of T)).Save

And it actually works... So I think that there is now more reason to think that there is a bug in the compiler or in VS.
If you go to the project's properties and click "Unused references" inside the references panel, Csla will be on that list. If you change the code to look like the line I just put a few lines above, then hitting Unused references will no longer output csla.dll.

This brings some clarity to the matter, but no solution.

Andrés

ajj3085 replied on Wednesday, May 31, 2006

Ahh,

I know in C# it doesn't matter if I don't have code that explicitly references something from Csla, CSC just includes the reference because I added it.

Perhaps there is a setting in VB.Net which attempts to remove unused references?  Actually I remember such a setting, but that was VB6.   If there's no option than it may very well be a bug in VBC.

Does anyone have any more info on this?  Like I said, I spend 100% of my time in C#.

Andy


Copyright (c) Marimer LLC