In this blog post I will talk about the Enhancer – an integral part of Telerik Data Access which often goes unnoticed. The Enhancer is the tool responsible for enabling you to use simple POCO classes in your Telerik Data Access Models and therefore making the development process easier.  Let’s see what this tool does for us.

What is the Enhancer and why is it Needed?

The Enhancer is the tool which makes the classes of your model persistent, adds automatic change tracking and lazy loading logic. All of this is done automatically and without using any reflection! This shortens development time as you do not need to add any specific logic to the classes yourself and the lack of reflection assures optimal performance. The Enhancer is called as a post build step to inject the code required to facilitate the aforementioned functionality in the persistent classes of the model. To illustrate this, consider the code of the very simple User class which is a part of a Telerik Data Access Model:

public partial class User
{
    private int _userId;
    public virtual int UserId
    {
        get
        {
            return this._userId;
        }
        set
        {
            this._userId = value;
        }
    }
        
    private string _userName;
    public virtual string UserName
    {
        get
        {
            return this._userName;
        }
        set
        {
            this._userName = value;
        }
    }
        
    private string _password;
    public virtual string Password
    {
        get
        {
            return this._password;
        }
        set
        {
            this._password = value;
        }
    }
}

As you can see, this persistent class is no different than any POCO class. Let’s examine what will happen with this class after we build the project containing the model. Opening the resulting assembly using Telerik Just Decompile will reveal that the User class now has the following code:

public class User : PersistenceCapable
{
    private int _userId;

    private string _userName;

    private string _password;

    public virtual string Password
    {
        get
        {
            return User.OpenAccessEnhancedGet_password(this);
        }
        set
        {
            User.OpenAccessEnhancedSet_password(this, value);
        }
    }

    public virtual int UserId
    {
        get
        {
            return User.OpenAccessEnhancedGet_userId(this);
        }
        set
        {
            User.OpenAccessEnhancedSet_userId(this, value);
        }
    }

    public virtual string UserName
    {
        get
        {
            return User.OpenAccessEnhancedGet_userName(this);
        }
        set
        {
            User.OpenAccessEnhancedSet_userName(this, value);
        }
    }

    public User()
    {
    }
}

There are several key differences. The User class now implements the PersistenceCapable interface, additionally the code in the getters and setters of the properties has been changed. You may notice that the methods called in the getters and setters for the properties are not present in the decompiled code. That’s because you see is only a fraction of the injected code - there is a number of additional members which are not shown by default. To reveal the full code you would need to enable the Show compiler generated types and members option in Just Decompile. All these modifications make the class persistent capable, allow Telerik Data Access to automatically track the changes that occur in it and facilitate the lazy loading. Essentially the User class has been enhanced so that the Telerik Data Access Runtime can operate with it.

How is the Enhancer Integrated in a Project?

Having the Enhancer called as a post build step is only required for projects which contain a Telerik Data Access Model. In such projects, the Enhancer is integrated by importing the OpenAccess.targets file in the .csproj or .vbproj. The import is added automatically to the MSBuild script contained in the .csproj or .vbproj file when a Domain Model or Fluent Model is added to the project. Do note that the import is added after after the one for the .targets file of the respective programming language (C# in this case):

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Condition="Exists('$(MSBuildExtensionsPath)\OpenAccess.targets')" Project="$(MSBuildExtensionsPath)\OpenAccess.targets" />

The imported OpenAccess.targets file is located in the MSBuild directory denoted by the MSBuildExtensionsPath. That being said, you can make a local copy of the .targets file and change the path to import it instead, should your scenario require you to do so. Furthermore you can even copy the Enhancer itself locally and load the local copy from the .targets file. This same approach is used in our Telerik.Data.Access.Fluent NuGet package.

The OpenAccess.targets file verifies that the enhancement process can be executed and calls the Enhancer to do so. It also defines the default settings which control the behavior of the Enhancer:

<PropertyGroup>
    <UseXmlMapping Condition="'$(UseXmlMapping)'==''">true</UseXmlMapping>
    <UseAttributeMapping Condition="'$(UseAttributeMapping)'==''">true</UseAttributeMapping>
    <UseFluentMapping Condition="'$(UseFluentMapping)'==''">true</UseFluentMapping>
    <OpenAccessPath Condition="'$(OpenAccessPath)'==''">C:\Program Files\Telerik\Data Access\</OpenAccessPath>
    <EnhancerAssembly Condition="'$(EnhancerAssembly)'==''">$(OpenAccessPath)\sdk\enhancer.exe</EnhancerAssembly>
    <EnhancerVerboseMode Condition="'$(EnhancerVerboseMode)'==''">3</EnhancerVerboseMode>
    <Use64BitEnhancer Condition="'$(Use64BitEnhancer)'=='' And '$(PlatformTarget)'=='x64'">true</Use64BitEnhancer>
    <ValidateMapping Condition="'$(ValidateMapping)'==''">false</ValidateMapping>
</PropertyGroup>

These default settings can be customized to suit your needs directly in the .csproj or .vbproj which imports the OpenAccess.targets file. This way you are able to modify the behavior of the Enhancer only for the current project without changing it globally. For example the following MSBuild script placed before the import of the OpenAccess.targets file will set the Verbose Mode of the Enhancer to 2 (as opposite to 3 which is the default value) so that only errors would be shown in the Output window:

<PropertyGroup>
    <EnhancerVerboseMode Condition="'$(EnhancerVerboseMode)'==''">2</EnhancerVerboseMode>
</PropertyGroup>

For more information about the settings defined by the OpenAccess.targets file, you can refer to our documentation about it.

The Enhancer is one of the most important aspects of Telerik Data Access as it is one of the key elements to making the development of a Data Access Layer quick and easy. Having an understanding of its function can help you modify the development environment or the Enhancer behavior for a given project according to potential specific requirements.

Download Data Access
About the Author

Kristian Nikolov

Kristian Nikolov is Support Officer.

Related Posts

Comments