Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I convert a dynamic proxy into a POCO?

I was trying trying to serialize a domain model and ran into an issue where I need to convert a dynamic proxy into a POCO. The issue I ran into was that circular references exist by way of virtual properties in the model. Although I attempted to use [ScriptIgnore] in order to have the serializer not parse those properties, it still does. I believe that this is because the objects are dynamic proxies and there is still some remnants in the properties which cause the parser to enter (which in turn causes a recursion error "circular reference" - I tried limiting the recursion to 3 steps but I got an error of "Recursive steps exceeded").

How can I convert an object from a dynamic proxy to a POCO so that it can be serialized?

Edit: Simple example

public class One : BaseViewModel
{
    public int OneId { get; set; }
    public virtual ICollection<Two> Two { get; set; }
}

public class Two
{
    public int TwoId { get; set; }
    public int OneId { get; set; }
    [ScriptIgnore]
    public virtual One One { get; set; }
}

public abstract class BaseViewModel
{
    public string AsJson()
    {
        var serializer = new JavaScriptSerializer();
        return serializer.Serialize(this);
    }
}
like image 382
Travis J Avatar asked Jul 05 '12 17:07

Travis J


People also ask

What is dynamic proxy?

A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface.

What is dynamic proxy in Entity Framework?

Dynamic Proxy IT can also be said that it is a runtime proxy classes like a wrapper class of POCO entity. You can override some properties of the entity for performing actions automatically when the property is accessed. This mechanism is used to support lazy loading of relationships and automatic change tracking.


1 Answers

As an alternative to Jim's Automapper solution, I've had some success with the 'Mapping' (shallow copying) the POCO proxy to an instance of the same POCO. The simple way to do this is to modify the template file that generates the POCO to include a ToSerializable() method, so the POCO classes look like this:

public partial class cfgCountry
    {
        public cfgCountry()
        {
            this.People = new HashSet<Person>();
        }

        [Key]
        public int CountryID { get; set; }
        public string Name { get; set; }
        public int Ordinal { get; set; }

        public virtual ICollection<Person> People { get; set; }

        public cfgCountry ToSerializable()
        {
            return new cfgCountry()
            {
            CountryID = this.CountryID,
            Name = this.Name,
            Ordinal = this.Ordinal,
            };
        }
    }

Here's the function I've added to the POCO template (tt) file to create the ToSerializable function (Such an ugly syntax.):

<#+
void WriteToSerializableMethod (CodeGenerationTools code, IEnumerable<EdmProperty> primitiveProperties, EntityType entity)
{

#>
public <#=code.Escape(entity)#> ToSerializable()
{
    return new <#=code.Escape(entity)#>()
    {
<#+
    foreach(var edmProperty in primitiveProperties)
    {
#>
    <#=edmProperty.Name#> = this.<#=edmProperty.Name#>,
<#+
    }
#>
    };
}
<#+
}
#>

It's not perfect, since you need to remember to return foo.ToSerializable() rather than foo itself whenever you expect a result to be serialized, but I hope its useful to somebody.

like image 142
daveharnett Avatar answered Nov 04 '22 07:11

daveharnett