Domenic Domenic - 1 month ago 10
C# Question

Generating immutable value object in C#: PostSharp or T4 templates?

I'm getting sick of boilerplate immutable value object code. Would either PostSharp or T4 templates allow me to do the following transformation?

Input:

public struct Name
{
public string FirstName;
public string LastName;
}


Output:

public struct Name : IEquatable<Name>
{
private readonly string firstName;
private readonly string lastName;

public string FirstName { get { return this.firstName; } }
public string LastName { get { return this.lastName; } }

public Name(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}

public bool Equals(Name other)
{
return this.FirstName == other.FirstName && this.LastName == other.LastName;
}
public override bool Equals(object obj)
{
return obj is Name && this.Equals((Name)obj);
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
if (this.FirstName != null)
{
hash = hash * 29 + this.FirstName.GetHashCode();
}
if (this.LastName != null)
{
hash = hash * 29 + this.LastName.GetHashCode();
}
return hash;
}
}

public static bool operator==(Name a, Name b)
{
return a.Equals(b);
}
public static bool operator !=(Name a, Name b)
{
return !(a == b);
}
}


Obviously PostSharp would require a
[MakeImmutable]
annotation, which is fine. I'd want the option of generating either a
class
or
struct
depending on the original type. Also note that
GetHashCode
would have to omit the
null
checks for value-type members.

I am fairly sure either technology has this capability, but having not been anything but a consumer of PostSharp aspects/T4 templates myself, I don't know which would be a better or easier one for this task. Whichever answer you give, I'll go spend a day or two learning enough to make this work :).

Answer

It looks like you want to just decorate your struct with boilerplate stuff, so PostSharp is going to be the way to go. The reason why is because with T4 you would need to

  1. Find all objects that need to be changed (which still requires attributes or some type of marker)
  2. Make sure you don't already have the changes applied to the struct
  3. Use EnvDTE to add the items (not always consistent)

See http://table2dto.codeplex.com for great T4 example of doing this

To do this you would need to employ the use of EnvDTE (see http://dfactor.codeplex.com for code on how to do this)

The problem is, if you need to generate boilerplate code that you need to use at design time (which it doesnt look like you have anything) then it's going to require some thinking to get PostSharp to work for you.

PostSharp is going to be your best bet.

Comments