obtenido de aqui
A new programming paradigm has been born in distant land of Java. Qi4j introduces the first Composite Oriented Programming (COP) concept to the world, and has drawn massive interest among Java crowd ever since.
It drove me to start a work on implementing Composite Orientation on .Net as a project named Composheep. This will be an open-source lightweight COP framework (as defined by Qi4j) that I will build incrementally as I write each step on this blog as “Roll Your Own COP” series. I publish the project in CodePlex as LGPL.
Let’s start from the mission of COP. One of the biggest flaws of OOP is that it’s not object oriented at all. If anything, OOP is Class-Oriented, since class is the primary citizen that all objects are derived from. Not the other way round.
As an example, I am a programmer at work, a driver in a car, a researcher in kitchen, and a hunter and a pray in the jungle. As an object, my role (class) constantly changes depending on contexts. Some objects also traverses different scope boundaries. For instance, a Person will have its classes changing over time. New abilities are learnt, from Kid, Student, Dancer, Ninja, and he will eventually due, but it doesn’t mean that the Person object should be deleted from the system since the “memory” of him may live for long time. In a conventional OOP system, we will need to transfer some of the states across instances of different classes. In Composite Oriented Programming, they are all ONE instance. We assign role (Class) to an object. Not instantiating objects based on a destined class. Object is therefore the primary citizen of COP. Please visit Qi4j site for more detail.
One of the most important COP concepts is mixin, in which multiple reusable classes are mixed to form a solid composite. It relies much on Java class generation technique, in which .net is always known far inferior. But, as the first part of the series, I will show how easy it actually is to build our own Mixins implementation on .net using Castle DynamicProxy, in only 15 minutes.
Our objective is to achieve a robust Mixins builder that is smart enough to:
- Handle both properties and methods
- Differentiate parameters overload. E.g. foo() and foo(string)
- Handle generic methods. E.g. foo<T>()
- Differentiate generics overload. E.g. foo<T>() and foo<T,Y>()
- Declarative programming using attributes
As a sample use-case, first I will define a composite of Person that is composed from 2 mixins: HasName and CanFight. I want to define the composite in the following fashion:
Here is the definition of the mixins:
The following is how I want the client code to be:
We instantiate an object of Person, whose implementation is generated dynamically by mixing HasNameImpl and Fighter together to form a complete Person. This way, we will be able to separate a class into smaller chunks of fragment (mixin) that can be reused effectively.
I think this use simple use-case provides a good coverage to all our 5 requirements. It exploits the use of properties, methods with overloaded parameters, and methods with overloaded generics.
Now, to make this work, we will need to write the CompositeBuilder as part of our Composheep solution. We will be using Castle DynamicProxy, which is a lightweight proxy generator used in many open-source frameworks like nHibernate, Windsor, Aspect#, etc.
Here is the implementation of CompositeBuilder. It searches for MixinAttributes in supplied type, then grab the mixin implementer types that was provided as attribute parameter.
ProxyGenerator is an API from Castle DynamicProxy that we use to dynamically define implementation of composite interface. The most important part of this only method is that in each mixin type defined in mixin attribute, we use default constructor to instantiate the mixin, and pass it to CompositeInterceptor. It’s a custom proxy interceptor that we will create to handle each composite method invocation to its corresponding mixin implementation.
Here is the code for CompositeInterceptor.
The idea is that AddMixin method will map each method signature with a mixin instance in a Dictionary. Therefore, when we intercept a proxy method invocation, we will be able to lookup the dictionary for the method signature, and get the mixin instance. Finally, the invocation will be redirected to that mixin instance.
The easiest way to lookup matching method signature (in FindMixin method) is by using MethodInfo.ToString() since it gives us the method name, parameters types, return type, and generic parameters. So we will be using this as the key of the Dictionary as well.
The only problem with generic parameter is that we will be storing open-generic method signature, for example, string Kick() in AddMethod method during interface introspection. But during invocation, we will get passed with a closed-generic method, for instance, string Kick(). To get around this, we put 2 lines on top of FindMixin:
It converts void Kick() back into void Kick(). And this is all we need to build our mixin builder! Run the application, and this is what we got:
Just few minutes of pretty straightforward code and we’ve got the building block for our Composheep in place. You can download the code for this episode here. Coming next, in the second episode, we will be building the second features of COP: concerns and side-effects.
A new programming paradigm has been born in distant land of Java. Qi4j introduces the first Composite Oriented Programming (COP) concept to the world, and has drawn massive interest among Java crowd ever since.
It drove me to start a work on implementing Composite Orientation on .Net as a project named Composheep. This will be an open-source lightweight COP framework (as defined by Qi4j) that I will build incrementally as I write each step on this blog as “Roll Your Own COP” series. I publish the project in CodePlex as LGPL.
Let’s start from the mission of COP. One of the biggest flaws of OOP is that it’s not object oriented at all. If anything, OOP is Class-Oriented, since class is the primary citizen that all objects are derived from. Not the other way round.
As an example, I am a programmer at work, a driver in a car, a researcher in kitchen, and a hunter and a pray in the jungle. As an object, my role (class) constantly changes depending on contexts. Some objects also traverses different scope boundaries. For instance, a Person will have its classes changing over time. New abilities are learnt, from Kid, Student, Dancer, Ninja, and he will eventually due, but it doesn’t mean that the Person object should be deleted from the system since the “memory” of him may live for long time. In a conventional OOP system, we will need to transfer some of the states across instances of different classes. In Composite Oriented Programming, they are all ONE instance. We assign role (Class) to an object. Not instantiating objects based on a destined class. Object is therefore the primary citizen of COP. Please visit Qi4j site for more detail.
One of the most important COP concepts is mixin, in which multiple reusable classes are mixed to form a solid composite. It relies much on Java class generation technique, in which .net is always known far inferior. But, as the first part of the series, I will show how easy it actually is to build our own Mixins implementation on .net using Castle DynamicProxy, in only 15 minutes.
Our objective is to achieve a robust Mixins builder that is smart enough to:
- Handle both properties and methods
- Differentiate parameters overload. E.g. foo() and foo(string)
- Handle generic methods. E.g. foo<T>()
- Differentiate generics overload. E.g. foo<T>() and foo<T,Y>()
- Declarative programming using attributes
As a sample use-case, first I will define a composite of Person that is composed from 2 mixins: HasName and CanFight. I want to define the composite in the following fashion:
Note that Person, as a composite, is defined as an interface. We won’t write any implementation of Person since it will be automatically derived by composing 2 mixin implementations together. We declaratively specify that we wish to use HasNameImpl and Fighter as mixin implementor by using Mixin attribute.
1
[Mixin(
typeof
(HasNameImpl),
typeof
(Fighter))]
2
public
interface
Person: HasName, CanFight
3
{
4
}
Here is the definition of the mixins:
And the following is the implementation of each mixins:
01
public
interface
HasName
02
{
03
string
FirstName{
get
;
set
;}
04
string
LastName {
get
;
set
;}
05
06
string
IntroduceSelf();
07
string
IntroduceSelf(
string
target);
08
}
09
10
public
interface
CanFight
11
{
12
string
Kick<Target>();
13
string
Kick<LTarget, RTarget>();
14
}
01 | public class HasNameImpl: HasName |
02 | { |
03 | public string FirstName { get ; set ;} |
04 | public string LastName { get ; set ;} |
05 |
06 | public string IntroduceSelf() |
07 | { |
08 | return Console.Writeln( |
09 | "Hi there, I am {0} {1}" , |
10 | FirstName, LastName); |
11 | } |
12 |
13 | public string IntroduceSelf( string target) |
14 | { |
15 | return Console.Writeln( |
16 | "Hi {0}, I am {1} {2}" , |
17 | target, FirstName, LastName); |
18 | } |
19 | } |
01 | public class Fighter: CanFight |
02 | { |
03 | public string Kick<Target>() |
04 | { |
05 | return Console.Writeln |
06 | ( "Roundhouse kick to {0}" , |
07 | typeof (Target).Name); |
08 | } |
09 |
10 | public string Kick<LTarget, RTarget>() |
11 | { |
12 | return Console.Writeln |
13 | ( "Left foot to {0}, and right foot to {1}" , |
14 | typeof (LTarget).Name, |
15 | typeof (RTarget).Name); |
16 | } |
17 | } |
1 | CompositeBuilder builder = new CompositeBuilder(); |
2 | Person person = builder.BuildComposite<Person>(); |
3 |
4 | person.FirstName = "Hendry" ; |
5 | person.LastName = "Luk" ; |
6 | person.IntroduceSelf()); |
7 | person.IntroduceSelf( "Goofy" )); |
8 | person.Kick<Dog>()); |
9 | person.Kick<Dog, DebtCollector>()); |
I think this use simple use-case provides a good coverage to all our 5 requirements. It exploits the use of properties, methods with overloaded parameters, and methods with overloaded generics.
Now, to make this work, we will need to write the CompositeBuilder as part of our Composheep solution. We will be using Castle DynamicProxy, which is a lightweight proxy generator used in many open-source frameworks like nHibernate, Windsor, Aspect#, etc.
Here is the implementation of CompositeBuilder. It searches for MixinAttributes in supplied type, then grab the mixin implementer types that was provided as attribute parameter.
01 | public class CompositeBuilder |
02 | { |
03 | private ProxyGenerator generator = new ProxyGenerator(); |
04 |
05 | public T BuildComposite<T>() where T : class |
06 | { |
07 | CompositeInterceptor interceptor = new CompositeInterceptor(); |
08 |
09 | object [] attributes = |
10 | typeof (T).GetCustomAttributes( typeof (MixinAttribute), true ); |
11 | foreach (MixinAttribute mixin in attributes) |
12 | { |
13 | foreach (Type mixinType in mixin.Types) |
14 | interceptor.AddMixin(Activator.CreateInstance(mixinType)); |
15 | } |
16 |
17 | return generator.CreateInterfaceProxyWithoutTarget(interceptor); |
18 | } |
19 | } |
Here is the code for CompositeInterceptor.
01 | internal class CompositeInterceptor : IInterceptor |
02 | { |
03 | Dictionary methodTargetMap = |
04 | new Dictionary(); |
05 |
06 | public void AddMixin( object mixin) |
07 | { |
08 | Type targetType = mixin.GetType(); |
09 |
10 | MethodInfo[] methods = |
11 | targetType.GetMethods( |
12 | BindingFlags.Instance | |
13 | BindingFlags.Public | |
14 | BindingFlags.NonPublic); |
15 |
16 | foreach (MethodInfo method in methods) |
17 | { |
18 | // Skip members declared in System.Object |
19 | if (method.DeclaringType == typeof ( object )) |
20 | continue ; |
21 |
22 | methodTargetMap.Add(method.ToString(), mixin); |
23 | } |
24 | } |
25 |
26 | // Implementing IInterceptor.Intercept method |
27 | public void Intercept(IInvocation invocation) |
28 | { |
29 | object target = FindMixin(invocation.Method); |
30 | if (target == null ) |
31 | throw ( new NotImplementedException()); |
32 |
33 | invocation.ReturnValue = |
34 | invocation.Method.Invoke( |
35 | target, invocation.Arguments); |
36 | } |
37 |
38 | private object FindMixin(MethodInfo callMethod) |
39 | { |
40 | if (callMethod.IsGenericMethod) |
41 | callMethod = callMethod.GetGenericMethodDefinition(); |
42 |
43 | foreach (String method in methodTargetMap.Keys) |
44 | { |
45 | if (method == callMethod.ToString()) |
46 |
47 | return methodTargetMap[method]; |
48 | } |
49 | return null ; |
50 | } |
51 | } |
The easiest way to lookup matching method signature (in FindMixin method) is by using MethodInfo.ToString() since it gives us the method name, parameters types, return type, and generic parameters. So we will be using this as the key of the Dictionary as well.
The only problem with generic parameter is that we will be storing open-generic method signature, for example, string Kick() in AddMethod method during interface introspection. But during invocation, we will get passed with a closed-generic method, for instance, string Kick(). To get around this, we put 2 lines on top of FindMixin:
1 | if (callMethod.IsGenericMethod) |
2 | callMethod = callMethod.GetGenericMethodDefinition(); |
Just few minutes of pretty straightforward code and we’ve got the building block for our Composheep in place. You can download the code for this episode here. Coming next, in the second episode, we will be building the second features of COP: concerns and side-effects.
No hay comentarios:
Publicar un comentario