Silverlight without PropertyInfo

Silverlight without PropertyInfo

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


mhnyborg posted on Saturday, February 14, 2009

Is it possible to use SL and object factor without PropertyInfo?

If it's possible then what am I loosing if I use normal property gets/set and backing fields like old CSLA 2.

Why am I asking this? because I would like to try to use my NH classes as CSLA classes. I can do that if I use partial classes. In SL I can use a partial class that inherit from businessbass and in the NH lib I can put my business logic in another partial class.

So I am only going to share the properties.

 

 

RockfordLhotka replied on Saturday, February 14, 2009

Yes, you can use CSLA .NET for Silverlight without the RegisterProperty()/PropertyInfo<T> concept.

To do this you must implement IMobileObject in your class (on both sides of the wire: Silverlight and .NET), which will force you to implement four methods where:

  1. You put all your private field values into the serialization stream
  2. You take all the your private field values from the serialization stream
  3. You delegate serialization to child objects you reference
  4. You delegate deserialization to child objects you reference

You can look at Csla.Core.MobileObject to see the implementation of this interface used by all the CSLA class (and Csla.Core.MobileList for lists, etc).

Alternately, as you note, you can use partial classes or other techniques to somehow inherit from MobileObject, BusinessBase or other CSLA base classes. But ultimately the key is to inherit from a MobileXYZ base class so you get the pre-existing IMobileObject implementation.

However, if you are using private fields you must implement methods that do items 1 and 2 above. That is inescapable.

This is all necessary because there's no clone-level serializer in Silverlight, nor do the technologies required to build such a serializer exist. The CSLA MobileFormatter does clone-level serialization in a way that avoids the limitations of Silverlight - but does require the participation of each object in the object graph.

These blog posts should be useful:

http://www.lhotka.net/weblog/CSLALightObjectSerialization.aspx

http://www.lhotka.net/weblog/CSLALightSerializationImplementation.aspx

http://www.lhotka.net/weblog/SilverlightSerializer.aspx

mhnyborg replied on Saturday, February 14, 2009

Thanks for answering so fast.

I always like the way you are answering questions. They are not just hints but always point you to a solution. The solution is not always what you want but it gets the job done.

Hope that you soon have some time to write more about SL.

 

AaronH replied on Friday, August 13, 2010

I am having problem sending members (custom types) exposed as properties of business objects to silverlight.  These members are are plain POCO objects.

 

I have a business object that persists its properties to fields in a table.  Except for one property, that is actually being serialized as XML and stored into a column.  I have supplied some easy to follow sample classes below (NOTE: these are purely fictitious classes for sake of brevity  and clarification purposes):

 

    public class Shape : BusinessBase
    {
        private static readonly PropertyInfo<DetailInfo> DetailInfoProperty = RegisterProperty<DetailInfo>(p => p.Detail);
        public DetailInfo Detail
        {
            get { return GetProperty(DetailInfoProperty); }
            set { SetProperty(DetailInfoProperty, value); }
        }
    }
 
    public abstract class DetailInfo
    {
    }
 
    public class CircleInfo : DetailInfo
    {
        public decimal Circumference { getset; } 
    }
 
    public class SquareInfo : DetailInfo
    {
        public decimal Area { getset; } 
    }

 

And here is how it would be used:

So when a concrete shape is saved, I am serializing the DetailInfo member as XML, and the result is an XML string that is saved in a field in a table.

        Shape shape = Shape.NewShape();
        CircleInfo info = new CircleInfo() { Circumference = 3.25 };
        shape.Detail = info;

 

This works fine.  I can also deserialize the object from the XML stored in the table field on the Fetch() of the shape.

So after I have a loaded Shape and its reinflated DetailInfo, I can utilize it on the .NET side.

The problem is on the sending of the DetailInfo object to the Silverlight client, WCF chokes, and states:

"CircleInfo is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."

 

After some investigation, it turns out that I need to  go a bit further than developing POCO objects exposed from Shape, and inherit from MobileObject.

So here is what I have now:

    public abstract class DetailInfo : MobileObject
    {
    }

 

And within CircleInfo…

        protected override void OnGetState(Csla.Serialization.Mobile.SerializationInfo info, Csla.Core.StateMode mode)
        {
            info.AddValue("Circumference", Circumference);
        }
 
        protected override void OnSetState(Csla.Serialization.Mobile.SerializationInfo info, Csla.Core.StateMode mode)
        {
            Circumference = info.GetValue<decimal>("Circumference");
        }

 

This works now. After I load a Shape and deserialize the shape’s DetailInfo (CircleInfo or SquareInfo), I can see its member on the Silverlight client.

Now suppose I need to add a new member to one of the DetailInfo classes, which is a new custom type:

    public class FurtherAttributes
    {
        public string MoreData { getset; }
    }

 

And I now add this to my CircleInfo class:

    public class CircleInfo : DetailInfo
    {
        public decimal Circumference { getset; } 
        public FurtherAttributes MoreAttributes { getset; }
    }

 

Once again,  WCF chokes, and states:

"FurtherAttributes is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."

So I've ensured now that FurtherAttributes inherits from MobileObject and overrides the OnGetState() and OnSetState() methods, but still getting it. 

I've applied the KnownAttribute attribute to the appropriate classes, but still no luck.

Has anyone faced this issue before?

Is there something else I need to be doing that I have forgotten about?

Thanks!

RockfordLhotka replied on Friday, August 13, 2010

What you must realize is that Silverlight doesn't have BinaryFormatter or NetDataContractSerializer, so we created our own MobileFormatter. The primary constraint we're operating under is that we can't use reflection to implement the formatter (which is why BF and NDCS don't exist - they rely on reflection).

This blog post illustrates the basic model for MobileFormatter: http://www.lhotka.net/weblog/CSLALightObjectSerialization.aspx

While we use WCF and the DataContractSerializer - it is generally only after we've sorted through the object graph to convert all the IMobileObject objects into serialization-safe DTOs. Any object in the graph that doesn't implement IMobileObject will generally cause failure.

Or to put it another way: MobileFormatter only works if every object in the graph implements IMobileObject.

This is because we can't use reflection - so the only way to serialize an object at the field level (which is what the data portal requires) is if every object in the object graph participates in the serialization process.

The base classes (MobileObject, etc) exist to simplify this process - since implementing IMobileObject directly is kind of a pain.

AaronH replied on Friday, August 13, 2010

Hi Rocky

Actually, all of my classes do implement IMobileObject:

 

public abstract class DetailInfo : MobileObject
{
}

public class CircleInfo : DetailInfo
{
    public decimal Circumference { getset; } 
    public FurtherAttributes MoreAttributes { getset; }
}

public class FurtherAttributes : MobileObject
{
    public string MoreData { getset; }
}

 

Any other thoughts?

 

RockfordLhotka replied on Friday, August 13, 2010

In that case you need to manage the object graph correctly. A child object isn't state - it is a child. IMobileObject has get/set methods for state, and a separate set of methods for children.

AaronH replied on Wednesday, August 18, 2010

Does anyone have a sample they could point me to?  I found the OnGetChildren() and OnSetChildren(), but not sure what to do with them.

Thanks!

RockfordLhotka replied on Wednesday, August 18, 2010

Look at MobileObject, MobileList, MobileDictionary, etc. You will have to duplicate most of the code in one or more of those classes to do what you want.

There are no standalone samples for how to build your own classes. We didn't set out to create a general purpose serializer - we set out to create something that meets the needs of CSLA - so the CSLA serializable base classes are the best and only samples out there.

Copyright (c) Marimer LLC