Print Page | Close Window

Property Interceptor prevents design time entity creation

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=3604
Printed Date: 13-May-2026 at 1:03am


Topic: Property Interceptor prevents design time entity creation
Posted By: gregweb
Subject: Property Interceptor prevents design time entity creation
Date 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



Replies:
Posted By: gregweb
Date 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.


Posted By: DenisK
Date 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.

uploads/912/DevForceWithMvvmLight.zip - uploads/912/DevForceWithMvvmLight.zip

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.

http://drc.ideablade.com/xwiki/bin/view/Documentation/code-samples-silverlight-5-beta#HKnownissues - http://drc.ideablade.com/xwiki/bin/view/Documentation/code-samples-silverlight-5-beta#HKnownissues

http://www.ideablade.com/forum/forum_posts.asp?TID=3247&title=designtime-problem - http://www.ideablade.com/forum/forum_posts.asp?TID=3247&title=designtime-problem

Please let me know if I'm missing anything.


Posted By: gregweb
Date 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


Posted By: DenisK
Date Posted: 04-Sep-2012 at 7:27pm
Can you tell what exception, if any, it is throwing on that piece of code?


Posted By: gregweb
Date 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


Posted By: mgood
Date 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() };
        }
    }


Posted By: gregweb
Date Posted: 05-Sep-2012 at 11:15am
Very good point Marcel, will never do that again!



Print Page | Close Window