Puzzling Behavior in BusinessBase

Puzzling Behavior in BusinessBase

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


Jav posted on Wednesday, December 30, 2009

Sorry for the idiotic Subject line for this message but I couldn't think of anything else.

Using Csla 3.8.1 (Silverlight).
After working with ReadOnlyBase derived objects all this time, I created my first parent-child BusinessBase pair of objects. Everything else looks fine except when, in the parent object, I am creating a Property to access the child object like:

if (!FieldManager.FieldExists(childObjectProperty ))
LoadProperty(childObjectProperty, ChildObject .NewChildObject ());
return GetProperty(childObjectProperty);


In the ChildObject.Server.cs I do have:
public static ChildObject NewChildObject ()
{
return DataPortal.CreateChild();
}

In the ChildObject.Client.cs I also have:
public static void NewChildObject(EvenetHandler stuff callback)
{
}

But the line ChildObject .NewChildObject () in the parent gives me the error:

No overload for method 'ChildObject' takes '0' arguments

If I Right click on the method call in the Parent and choose GoTo Definition, it takes me to ChildObject.Server to the correct NewChildObject () method.

If I change the child object's declaration from Csla.BusinessBase to Csla.ReadOnlyBase, this error promptly disappears (of course, there are other (expected) errors.

I have looked at the class declarations and they all appear correct, but obviously I am not doing something right.

Would appreciate a hint or two.

Javed

ajj3085 replied on Wednesday, December 30, 2009

CreateChild always runs on the client and it sounds like your NewChildObject method is only in the server side assembly.

Jav replied on Wednesday, December 30, 2009

In the ChildObject.Server.cs I have:
public static ChildObject NewChildObject ()
{
return DataPortal.CreateChild();
}

In the ChildObject.Client.cs I also have:
public static void NewChildObject(EvenetHandler stuff callback)
{
}

The NewChildObject is in both, ChildObject.Server as well as in ChildObject.Client. It is true that the NewChildObject on the client has the callback EventHandler argument and thus the error "No overload for method 'NewChildObject' takes '0' arguments". But that will always be the case because of the need for the callback EventHandler on the Client.

I am wondering if something else is screwed up in this pair of projects because if I "Clean Solution" followed by "Build Solution", I see an additional error:

\Documents\Visual Studio 2008\Projects\....\VisitClientLibrary\Bin\Debug\VisitLibrary.dll' could not be found. VisitLibrary is the NameSpace as well as the Assembly name of VisitServerLibrary and VisitClientLibrary projects - the two projects in question.

Javed

ajj3085 replied on Wednesday, December 30, 2009

The new error just means a project depends on VisitLibrary, which isn't building and thus there's no assembly for the dependant project to use to resolve types.

Are you getting a runtime error or compile error?

Jav replied on Wednesday, December 30, 2009

Thanks for your help.

The bin directory of my VisitClientLibrary was indeed empty at that time. The problem may have been with my WebService reference. I am not sure but after fiddling with the projects, the bin directory now has everything in it.

My error however persists - and it is a compile error. I decided to create another small Silverlight solution and moved my Parent and Child classes into it. I intended to attach it to this email to demonstrate the problem.

But lo and behold - no error! Compiler is happy and the project builds fine.

At this point, I think I will remove my existing, quite likely sick, projects and replace them with new projects and move my files into them. That will probably fix the problem.

Thanks for your help.

HAPPY NEW YEAR TO YOU AND Y'ALL.

Javed

ajj3085 replied on Thursday, December 31, 2009

Hmm... its possible that the project calling the NewChild() method wasn't looking at the business library which contained by the .Client and .Server files.  My understanding of Csla Light is that you have a BO assembly for Silverlight, which only includes the .Client files, and a BO assembly for your application server, which includes both.

But I don't know how you had things setup, so I have no idea!

Just don't be mislead by VS though; just because it figured out where the method lives doesn't mean that's how the compiler sees it.

Jav replied on Thursday, December 31, 2009

You are right that the ...ClientLibrary project will contain the Child.Client file and the ....ServerLibrary project the Child.Server file.
The Client file has Factory methods that only work asynchronously and therefore always have at least one argument, the EventHandler for callback, and the methods are declared public static void. The Server file also has (should it always have?) Factory methods that return the object, as in Windows version, and can have 0 argument.

It looks like that the magic is provided by the CslaDataProvider in the Silverlight xaml file. When calling the Factory method that expects the call back argument, CslaDataProdier adds the callback after any other parameters supplied by the programmer. If I was to call the same exact method manually in code, I'll have to supply the callback.

Here is where the problem originated. Problem started in the Property code that checks to see if Child exists, and if not to "Create" a new Child by calling - what else - the New.. factory method. The question is, which factory method? And with what parameters , i.e., with callback or without. In my little sample that I was about to post, I had the Server file Factory method with 0 arguments and compiler was happy but that method will never be called in Silverlight.

What is now happening in my project is an inconsistent behaviour. Sometimes everything works fine and the project actually runs, at other times I start getting an error - and it is always the code within the Child Property declaration.

I have a feeling that creating an object within the property declaration like that is going to be non-option in SL - but I may be wrong.

I think only Rocky can solve this dilemma.

Javed

ajj3085 replied on Thursday, December 31, 2009

Because the factory method is called asyc (which is required by silverlight), its possible for your property to return null... and your UI must handle this scenario correctly.

You can do it... but I'm afraid I can't be of much more help, as I've yet to delve into silverlight. The answer should be on the forum somewhere, as that's how I recall this issue.  Maybe searching for silverlight and lazy load will help.

Jav replied on Thursday, December 31, 2009

I have now tried using this in the Property Get:

get
{
if (!FieldManager.FieldExists(childProperty))
{
Child.NewChild(ChildKey,(o, e) =>
{
LoadProperty(childProperty, (Child)o);
});
}
return GetProperty(childProperty);
}

I do have an overload of NewChild that expects Int32 ChildKey plus the callback - in other words 2 arguments. What is maddening is the same old error:

"No overload for method 'NewChild' takes '2' arguments"

I have a second overload of NewChild with only the callback. If I remove the ChildKey from NewChild call, I get this:

"Cannot convert lambda expression to type 'int' because it is not a delegate type"

I declare!!

Copyright (c) Marimer LLC