José F. Romaniello

Las aventuras y desventuras de un codificador.

Rob Eisenberg sent me a link to a JavaScript framework named TraitsJS. I liked this example:

2-TCircle

I thought this was interesting to try using my Heredar project, so here is the code for this example:

public interface IEquality
{
    bool Equals(IEquality other);
    bool Differs(IEquality other);
}

public abstract class Equality : IEquality
{
    public abstract bool Equals(IEquality other);

    public bool Differs(IEquality other)
    {
        return !Equals(other);
    }
}

public interface IMagnitude : IEquality
{
    bool Smaller(IMagnitude other);
    bool Greater(IMagnitude other);
    bool Between(IMagnitude min, IMagnitude max);
}

public abstract class Magnitude : IMagnitude
{
    public abstract bool Smaller(IMagnitude other);

    public abstract bool Equals(IEquality other);

    public abstract bool Differs(IEquality other);

    public bool Between(IMagnitude min, IMagnitude max)
    {
        return min.Smaller(this) && this.Smaller(max);
    }

    public bool Greater(IMagnitude other)
    {
        return !Smaller(other) && this.Differs(other);
    }
}

[ExtendWith(typeof(Equality), typeof(Magnitude))]
public class Circle
{
    public int Center { get; set; }

    public int Radious { get; set; }

    public double Area
    {
        get { return Math.PI * (Radious ^ 2); }
    }

    public bool Equals(IEquality other)
    {
        var otherCircle = other as Circle;
        if (otherCircle == null) return false;
        return otherCircle.Center == Center
               && otherCircle.Radious == Radious;

    }

    public bool Smaller(IMagnitude other)
    {
        var otherCircle = other as Circle;
        if (otherCircle == null) return false;
        return Radious < otherCircle.Radious;
    }
}

This example uses a feature of Heredar called Abstract Templates. The weaved class looks like:

public class Circle : IEquality, IMagnitude
{
    // Fields
    private Equality Equality_1;
    private Magnitude Magnitude_1;

    // Methods
    public Circle()
    {
        this.Equality_1 = new EqualityImpl(this);
        this.Magnitude_1 = new MagnitudeImpl(this);
    }

    public bool Between(IMagnitude min, IMagnitude max)
    {
        return this.Magnitude_1.Between(min, max);
    }

    public bool Differs(IEquality other)
    {
        return this.Equality_1.Differs(other);
    }

    public sealed override bool Equals(IEquality other)
    {
        Circle otherCircle = other as Circle;
        if (otherCircle == null)
        {
            return false;
        }
        return ((otherCircle.Center == this.Center) && (otherCircle.Radious == this.Radious));
    }

    public bool Greater(IMagnitude other)
    {
        return this.Magnitude_1.Greater(other);
    }

    public bool Smaller(IMagnitude other)
    {
        Circle otherCircle = other as Circle;
        if (otherCircle == null)
        {
            return false;
        }
        return (this.Radious < otherCircle.Radious);
    }

    public double Area
    {
        get
        {
            return (3.1415926535897931 * (this.Radious ^ 2));
        }
    }

    public int Center { get;  set; }

    public int Radious { get; set; }

    // Nested Types
    private class EqualityImpl : Equality
    {
        // Fields
        private Circle Circle;

        // Methods
        public EqualityImpl(Circle circle)
        {
            this.Circle = circle;
        }

        public override bool Equals(IEquality other)
        {
            return this.Circle.Equals(other);
        }
    }

    private class MagnitudeImpl : Magnitude
    {
        // Fields
        private Circle Circle;

        // Methods
        public MagnitudeImpl(Circle circle)
        {
            this.Circle = circle;
        }

        public override bool Differs(IEquality other)
        {
            return this.Circle.Differs(other);
        }

        public override bool Equals(IEquality other)
        {
            return this.Circle.Equals(other);
        }

        public override bool Smaller(IMagnitude other)
        {
            return this.Circle.Smaller(other);
        }
    }
}

Note; There is a lot of cases that TraitJs supports and Heredar doesn’t, take this is as a work in progress.

| More

Jimmy Bogard posted a very interesting post Autoprojecting LINQ queries. Few months ago, I started an experiment for doing exactly this. My code is here.

My experiment handle the same scenario Jimmy shown but also supports many to one relationships.

Suppose you have a domain class like this:

public class Person
{
  public virtual string Name   { get; set; }
  public virtual Person Parent { get; set; }
  public virtual Country Country { get; set; }
}

and a dto like this:

public class PersonDto
{
  public virtual string Name   { get; set; }
  public virtual string CountryName { get; set; }
  public virtual string ParentName  { get; set; }
  public virtual string ParentCountryName { get; set; }
}

you can automap the projection as follows:

var mapper = new Mapper();
mapper.AddMap<Person, PersonDto>();
var dtos = query<Person>().Select(mapper.GetProjection<Person, PersonDto>());

;

The call to mapper.GetProjection returns the following expression:

This query works very well with nhibernate.

Expression<Func<Person, PersonDto>> projection =
  person => new PersonDto
    {
     Name = person.Name,
     CountryName = person.Country != null ? person.Country.Name : string.Empty   
     ParentName = person.Parent != null ? person.Parent.Name : string.Empty    
     ParentCountryName = person.Parent != null ? (person.Parent.Country != null ? person.Parent.Country.Name : string.Empty) : string.Empty    
    }

The code is very simple and it is opensource. Feel free to enhance it :)

| More

I’ve released Heredar Alpha 1 yesterday and I wrote a lot of useful information in the wiki. Please have a look to the advanced templates pages to see the state of the art, and how it works.

I am looking forward to get some feedback and opinions.

Happy coding!

| More

Simon Cropp and I are working on a tool to add multiple inheritance support to the .net framework as a post build task (msbuild) using the glorious Mono.Cecil library. The project is hosted here.

Why multiple inheritance?

We are not interested in Multiple Inheritance as such, but in one specific case: Mixins. Mixins are an special case of multiple inheritance, where the inheritance doesn’t mean specialization as in single inheritance but means adding an specific functionality.

  • A simple way to think of mixins is as “an interface with implementation”. If you have written Java interfaces, you have surely found yourself writing the same implementations over and over for each class that implements the interface. A mixin lets you write the implementation once and have it automatically included in each class that uses it.

  • Mixins work best when they are small, independent units of functionality, orthogonal to other classes and mixins. If your mixins obey this guideline, then the model of how mixins work is very simple: it is as if the body of each mixin were copied textually into each class that uses it.  From OpenLaszlo site.

This concept is widely used in other languages such as Simula, Smalltalk, Perl, Javascript, Ruby and Python (more languages here).

Why static?

We know about other tools for creating mixins dynamically like Castle DynamicProxy, Spring.Net and LinFu. These tools work by creating a proxy type on runtime, and redirecting calls to each target or mixed instance. This work well for some use cases, but we found it doesn’t in others:

  • Sometimes you don’t own the activation of the instance. E.g. you want to use mixin with an entity but you don’t have control on the instantiation of the entity when it come from an ORM tool.
  • Type hell: lets say that you have a validation framework, configured to validate an specific class: Person. When working with dynamic proxies, you have an instance of PersonProxy instead of Person, so you will need to tell your validation framework somehow that PersonProxy must be validated as a Person.
  • Reflection-heavy scenarios like WPF sometimes fail.

How it works?

//Simple templates

public class Auditable : IAuditable
{
    public DateTime CreateDate { get; set; }
    public string CreatedBy { get; set; }
    public DateTime UpdateDate { get; set; }
    public string UpdateBy { get; set; }
}


public class ErrorInfo : IDataErrorInfo
{
    public object Target { get; set; }

    #region IDataErrorInfo Members

    public string this[string columName]
    {
        get { return Validator.Validate(Target, columName); }
    }

    public string Error
    {
        get { return Validator.Validate(Target); }
    }

    #endregion
}

//Your code

[ExtendWith(typeof(ErrorInfo), typeof(Auditable))]
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime Birthdate { get; set; }
}

//What gets compiled

public class Person : IAuditable, IDataErrorInfo
{
    private Auditable Auditable_1 = new Auditable();
    private ErrorInfo ErrorInfo_1 = new ErrorInfo();

    public Person()
    {
        this.ErrorInfo_1.Target = this;
    }

    public DateTime Birthdate { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
        
    //Auditable members
        
    public DateTime CreateDate
    {
        get
        {
            return this.Auditable_1.CreateDate;
        }
        set
        {
            this.Auditable_1.CreateDate = value;
        }
    }

    public string CreatedBy
    {
        get
        {
            return this.Auditable_1.CreatedBy;
        }
        set
        {
            this.Auditable_1.CreatedBy = value;
        }
    }
        
    public string UpdateBy
    {

        get
        {
            return this.Auditable_1.UpdateBy;
        }

        set
        {
            this.Auditable_1.UpdateBy = value;
        }
    }

    public DateTime UpdateDate
    {
        get
        {
            return this.Auditable_1.UpdateDate;
        }
        set
        {
            this.Auditable_1.UpdateDate = value;
        }
    }

    //dataerror info members
        
    public string Error
    {
        get
        {
            return this.ErrorInfo_1.Error;
        }
    }

    public string this[string columName]
    {
        get
        {
            return this.ErrorInfo_1[columName];
        }
    }
}

This is the current implementation now. In the beginning we though about cloning instruction per instruction but it is really hard when it comes to generics templates. Also with this approach you can debug mixed templates.

Simple configuration

You only need to add these few lines to the end of your project file.

2011-02-01_0837

No reference required

Just add the attribute to your project, it can be internal and that’s all. Heredar will find the attribute by name. Otherwise, you can add a reference to Heredar.dll (there is a version for standard .net, Silverlight and phone) use the attribute, and Heredar will remove the attributes and the reference after weaving.

| More