| Author |
Share Topic Topic Search Topic Options
|
gregweb
DevForce MVP
Joined: 10-Sep-2009
Location: Clearwater, Fl
Posts: 253
|
Post Options
Quote Reply
Topic: Property Interceptor prevents design time entity creation Posted: 03-Sep-2012 at 4:41pm |
|
I am using a Property Interceptor in a partial entity class and it works fine at run time:
[AfterSet(EntityPropertyNames.PercentComplete)]
MethodGoesHere...
However, in Visual Studio, the Entity can no longer be created by the designer and so I can't use design time data. (ie, it is no longer Blendable).
If I comment out the attribute, it becomes Blendable again.
Any suggestions on this? I really like binding to test data at design time as it makes UI design much faster.
Greg
|
 |
gregweb
DevForce MVP
Joined: 10-Sep-2009
Location: Clearwater, Fl
Posts: 253
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 9:34am |
|
Another issue along this line is that the RelatedEntityList<T> type is not design time creatable.
This means that if you have a UI with entity fields, and a grid for related items, the related items will not show in the grid at design time.
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 2:33pm |
Hi Greg,
I added the 2 items (PropertyInterceptor and RelatedEntityList) above to my design time data sample solution and didn't encounter any issue.
In the PropertyInterceptor case, I have both AfterSet and AfterGet, and I can see the AfterGet being applied and invoked.
Same thing with the RelatedEntityList. I have Customer and Orders and I can see my Orders mock data on the data grid.
One suggestion is to debug your design time data invocation when you bring your XAML up in the designer mode. You can do this by bringing up another copy of your solution and attach this solution to the other using Debug - Attach to Process. You can then put breakpoints and see what's going on.
I've attached my sample solution here. I'm using DevForce 6.1.8.1 and SL4.
If you're using SL5, please note that we have encountered known issues with design time data when SL5 is installed. Here's a couple of links that have more info.
Please let me know if I'm missing anything.
Edited by DenisK - 04-Sep-2012 at 2:36pm
|
 |
gregweb
DevForce MVP
Joined: 10-Sep-2009
Location: Clearwater, Fl
Posts: 253
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 6:04pm |
|
Hi Denis, Thanks very much for the sample.
The issue seemed to narrow down to the following code in the Interceptor:
if(args.Instance.CompletedOn == null)
args.Instance.CompletedOn = DateTime.UtcNow.ToLocalTime();
In any case, if I put in a designer check to not run the code at design time, then everything works fine.
Also, if I use OnPropertyChanged() instead of the interceptor, it also works just fine.
Also, VS2010 seems to show the designer more reliably - ie the same code in 12 does not show the designer, while opening it in 10 does. Then going back to 12 it does open propertly. Go figure!
Greg
Edited by gregweb - 05-Sep-2012 at 4:25am
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 04-Sep-2012 at 7:27pm |
|
Can you tell what exception, if any, it is throwing on that piece of code?
|
 |
gregweb
DevForce MVP
Joined: 10-Sep-2009
Location: Clearwater, Fl
Posts: 253
|
Post Options
Quote Reply
Posted: 05-Sep-2012 at 6:29am |
|
An error was being thrown on this line:
if(args.Instance.CompletedOn == null)...
The error was "Object Reference not set to instance of object" which makes no sense as it was a null check. The debugger showed the CompletedOn property was null.
In any case, I think the issue was that the AfterSet was being run during the object initialization so the object wasn't fully initialized. As soon as I set the property after the initialization, then it stopped throwing the error.
I tried recreating the issue in the sample issue to no avail, but at least it is working as expected now.
Thanks for the support!
Greg
|
 |
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 05-Sep-2012 at 10:45am |
Greg,
Code in the constructor is an anti-pattern that gets you in trouble as it just did. All a constructor should do is initialize the private fields and make sure the object is in a valid state. Initializing properties and calling methods should be done from other methods. Avoid getting/setting properties in the constructor. Getting or setting a property is an innocent looking method call, the setter/getter of the property. The setter/getter can do any number of things that will fail if the object isn't fully constructed yet, which is the case if the setter is called from within a constructor, and what happened in your case.
The safe way to create and initialize an Entity is by means of a factory method. Following is a simple example.
public class StaffingResource : AuditEntityBase { internal StaffingResource() { }
public static StaffingResource Create() { return new StaffingResource { Id = CombGuid.NewGuid() }; } }
|
 |
gregweb
DevForce MVP
Joined: 10-Sep-2009
Location: Clearwater, Fl
Posts: 253
|
Post Options
Quote Reply
Posted: 05-Sep-2012 at 11:15am |
|
Very good point Marcel, will never do that again!
|
 |