none
Reflection.Emit and partial classes RRS feed

  • Question

  • Hi everyone,

    I am trying to achieve something similar to the .NET Entity Framework, meaning to proxy an existing class such as a basic data model, and extend it with some specific code.
    There are several ways to do this, but after several tests, I came to the conclusion that, in my specific use case, the fastest solution, by far, was using Reflection.Emit. As a matter of fact, using the latter, I can instantiate an entity in about 0.03ms which is far better than the 0.89ms I could achieve by using a combinaison of the RealProxy and the System.Dynamic classes.
    I am however facing a major challenge, which I will try to explain with a simple exemple:

    The user-defined data model:

    public class Client
    {

    [DataMember]
    public virtual Guid Id{get;set;}

    [DataMember]
    public virtual string FirstName{get;set;}

    [DataMember] public virtual string LastName{get;set;}

    }


    The proxied data model, generated thanks to Relfection.Emit:

    public class ClientProxy
    : Client, INotifyPropertyChanged
    {

    private Guid _Id;
    private Guid _FirstName;

    public virtual Guid Id
    {
    get
    {
    return _Id;
    }
    set
    {
    _Id = value;
    if(this.PropertyChanged != null)
    {
    this.PropertyChanged("Id");
    }
    }
    }

    public virtual string FirstName
    {
    get
    {
    return _FirstName;
    }
    set
    {
    _FirstName = value;
    if(this.PropertyChanged != null)
    {
    this.PropertyChanged("FirstName");
    }
    }
    }

    public virtual string LastName
    {
    get
    {
    return _LastName;
    }
    set
    {
    _LastName = value;
    if(this.PropertyChanged != null)
    {
    this.PropertyChanged("LastName");
    }
    }
    }

    }


    The challenge:

    How can I replace an instance of the Client class by an instance of the ClientProxy class, at runtime?
    I tried making both the Client and the ClientProxy (renamed Client for the occasion) classes 'partial', but I would get an exception stating that Type[A] (Client) differs from Type[B] (ClientProxy). I take it throws this exception because the partial Client class generated with Emit is not from the same assembly as the data model.
    I googled for a way to "inject" my dynamic type into the assembly defining the Client data model for the exception not to be thrown again, but this seems impossible via Emit.
    How can I achieve this? It must be possible via Emit, for I believe this is the way the EntityFramework does the trick, am I wrong?
    If I am wrong, what are my options? CLR injection?

    Thanks in advance for your time and attention,

    Chad

    Thursday, May 21, 2015 9:16 AM

Answers

  • Hello Chad333,

    >> My aim is to track changes made to POCO entities (used for adding/inserting new items into the database) after they have been "attached" to a given database.

    Then the type is not a proxy one, for this, you could detect Change Tracking Using a Snapshot:

    https://msdn.microsoft.com/en-us/library/dd456848(v=vs.110).aspx

    >> Is that true?

    It is that EntityFramework with DbContext api uses the DbChangeTracker Class to monitor these changes of each entity.

    >> Or does EF, in a code-first approach, generates a partial class for all POCO entity classes that are contained by a given DataContext?

    For this, I may do not very understand it, as far as I know, for the code first approach, EF does not generate a partial class for these manually created entities,

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Chad333 Thursday, May 28, 2015 9:21 AM
    Monday, May 25, 2015 9:48 AM
    Moderator

All replies

  • Hello Chad,

    >>How can I achieve this? It must be possible via Emit, for I believe this is the way the EntityFramework does the trick, am I wrong?

    It is not clear what part you mean the Entity Framework uses the Emit, if for how Entity Framework generates these entities, as far as I know, Entity Framework uses the T4 template: http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx and generate these entities according the metadata. If you want to customize these generated entities, you could write yourself T4 template: https://msdn.microsoft.com/en-us/data/gg558520.aspx

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, May 22, 2015 5:38 AM
    Moderator
  • Hi Fred,

    First of all, thanks a bunch for your fast and very instructive answer, I was avsolutely unaware of T4 templates, you have opened the doors to a whole new world, and gave me great clues for the next step of my project. It did not, however, solve my problem, which I most certainly did not adequatedly expose.

    My aim is to track changes made to POCO entities (used for adding/inserting new items into the database) after they have been "attached" to a given database.
    It is easy to track change on an entity that your database return: suffices to emit a new dynamic type inheriting from the POCO entity type, overriding all virtual properties.
    However, I could not figure how to track changes made upon a POCO entity after it has been attached. After some further searches, I read that EF monitors changes made to attached entities thanks to the DbChangeTracker class, with vulgar brute force on the attached entities' properties.
    Is that true? Or does EF, in a code-first approach, generates a partial class for all POCO entity classes that are contained by a given DataContext?

    I hope I could make myself clearer.

    Thanks again for the time and attention

    Friday, May 22, 2015 7:51 AM
  • Hello Chad333,

    >> My aim is to track changes made to POCO entities (used for adding/inserting new items into the database) after they have been "attached" to a given database.

    Then the type is not a proxy one, for this, you could detect Change Tracking Using a Snapshot:

    https://msdn.microsoft.com/en-us/library/dd456848(v=vs.110).aspx

    >> Is that true?

    It is that EntityFramework with DbContext api uses the DbChangeTracker Class to monitor these changes of each entity.

    >> Or does EF, in a code-first approach, generates a partial class for all POCO entity classes that are contained by a given DataContext?

    For this, I may do not very understand it, as far as I know, for the code first approach, EF does not generate a partial class for these manually created entities,

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Chad333 Thursday, May 28, 2015 9:21 AM
    Monday, May 25, 2015 9:48 AM
    Moderator
  • Hello Fred,

    Thanks to some of the links and tips you gave me, I could figure out a way to achieve my aim. Many thanks, both for your very good answers and for the speed at which you posted back.

    Like in the Entity Framework, my framework now monitors changes made to POCO entities thanks to a DbChangeTracker object, and entities returned by my datasets are now proxies of the POCO class, defined at runtime thanks to Reflection.Emit. Finally, thanks to the awesome T4 links you gave me, I am able to generate all the code required to virtualize the data source, such as would codesmith or LinqToSql classes.

    I consider this post answered,

    Thanks again,

    Chad

    Thursday, May 28, 2015 9:21 AM