Welcome to Happil
In this project we aim to create a wrapper library around .NET Reflection.Emit API. The library should precisely fit two use cases of run-time type generation, which we have in mind:
- Implementation: Given a compiled interface or an abstract class, generate its fully functional implementation at run-time.
- Interception: Decorate objects at run-time for the handling of cross-cutting concerns.
We also have two important qualities in mind:
- Being easy: provide happy path for the two use cases; make it hard to create an invalid program.
- Being lightweight: generated programs should contain no inherent overhead and consume as little CPU cycles and memory as possible, even in large applications having thousands of interfaces to implement or intercept.
Alternatives to Happil
The motivation to launch this project comes from our experience trying to get things done with existing alternatives, namely:
- Castle DynamicProxy is an awesome library which provides an elegant, simple, and yet powerful way of decorating objects at runtime. Unfortunately, it is only good for the interception use case; implementing interfaces from scratch is not its home ground. Another concern is that it generates an invocation class for each member of each decorated type. In a large application, this can lead to generating tens of thousands of types - which is not really that lightweight.
- RunSharp is another great tool which allows creation of arbitrary dynamic types and code at run-time. It allows too much freedom though, which in the bottom line, makes it harder to implement either of our two use cases. With RunSharp, we feel it is too easy to make a mistake and generate an incorrect program. This library also has stability issues, from our experience, and it also looks like it is not longer maintained.
- FluentIL is a cute library which wraps the Reflection.Emit API. But again, the API it provides is too a low level, and it again makes it harder to achieve the two use cases.
Show Me The Money
Three - given an interface of a data transfer object:
public interface ICustomer
{
int Id { get; set; }
string FullName { get; set; }
string EmailAddress { get; set; }
}
Two - plus an implementation convention:
DeriveClassFrom<object>()
.ImplementInterface<ICustomer>()
.AllProperties().ImplementAutomatic();
One - plus a decorator convention:
public class DataContractDecorator : ClassDecoratorBase
{
public override void OnClassType(ClassType classType, ClassWriterBase writer)
{
writer.Attribute<DataContractAttribute>(values => values.Named(a => a.Namespace, "http://mydto/customer"));
}
public override void OnProperty(PropertyMember member, Func<PropertyDecorationBuilder> decorate)
{
decorate().Attribute<DataMemberAttribute>();
}
}
GO!
[DataContract(Namespace = "http://mydto/customer")]
public sealed class CustomerDto : ICustomer
{
private int m_Id;
private string m_FullName;
private string m_EmailAddress;
[DataMember]
public int Id
{
get { return this.m_Id; }
set { this.m_Id = value; }
}
[DataMember]
public string FullName
{
get { return this.m_FullName; }
set { this.m_FullName = value; }
}
[DataMember]
public string EmailAddress
{
get { return this.m_EmailAddress; }
set { this.m_EmailAddress = value; }
}
}