Thursday, 21 February 2008

This is the fourth of a series about how to go about using postcompilation in your solutions. You can read it as a tutorial on how to use PostSharp. I am very much new to that framework, but the power it provides could seriously change how you build your applications. While working on the EF contrib project, I had to dive into PostSharp, and I hope to share some of the things I learned along the way.

This post introduces the first real step I took: the compound aspect.

The full table of contents:

  • Introducing Entity Framework Contrib- Easy IPoco implementation V 0.1
  • Part II, Postsharp Core versus Postsharp Laos
  • Part III, the compound aspect
  • Part IV, the PocoInterfaceSubaspect (composition aspect)
  • Part V, hooking up the weaver
  • Part VI, the EdmScalarWeaver
  • Recap

    We wish to create an attribute that can be placed on top of our ordinary Poco class, that will magically transform it into a class that implements the 3 IPoco interfaces. These are needed by the Entity Framework to do it's work. We will use PostSharp to do this.
    Our previous post talked about the composite attribute and how it allows you to combine multiple actions into one attribute. That's easier to use for the endusers.

    This post we will look into the PocoInterfaceSubAspect and how it does it's job.

    The Composition aspect

    You can remember placing the PocoInterfaceSubAspect on the element like so:

                // implement the three IPOCO interfaces on the class
                collection.AddAspect(targetType, new PocoInterfacesSubAspect());

    Postsharp will instantiate our aspect during it's weaving. Our aspect inherits from CompositionAspect. Let's take a step back and discuss what the CompositionAspect does.

    The compositionAspect is an extremely powerful aspect which allows you to implement an interface onto another object. So let's say you want to make an object be an iList at runtime, without dealing with it in your source: use composition to implement iList!

    We are implementing the three iPoco interfaces. Because the CompositionAspect wants one type to composite (and I did not feel like doing it three times) I created a facade interface:

        public interface IPocoFacade : IEntityWithChangeTracker, IEntityWithKey, IEntityWithRelationships
        {
        }

    Now, how does the weaver go about using this aspect to actually implement the code needed? It will ask for the public interface to inject and then also ask for an implementation object. The implementation object is the one that gets to do the dirty work. PostSharp will basically inject that implementation object into your object and then create all your interface code to just use that implementation object.

    The PocoInterfacesSubAspect

    The complete aspect looks like this:

        [Serializable]
        sealed class PocoInterfacesSubAspect : CompositionAspect
        {

            public override object CreateImplementationObject(InstanceBoundLaosEventArgs eventArgs)
            {
                return new PocoImplementation(eventArgs.Instance);
            }

            public override Type GetPublicInterface(Type containerType)
            {
                return typeof(IPocoFacade);
            }

            /// <summary>
            /// Gets weaving options.
            /// </summary>
            /// <returns>Weaving options specifying that the implementation accessor interface (<see cref="IComposed{T}"/>)
            /// should be exposed, and that the implementation of interfaces should be silently ignored if they are
            /// already implemented in the parent types.</returns>
            public override CompositionAspectOptions GetOptions()
            {
                return
                    CompositionAspectOptions.GenerateImplementationAccessor |
                    CompositionAspectOptions.IgnoreIfAlreadyImplemented;
            }
        }

     

    Clearly, we are more interested in the implementation object.

    The implementation

    Part of the implemenation object looks like this:

       class PocoImplementation : IPocoFacade
        {
            private readonly object instance;

            public PocoImplementation(object instance)
            {
                this.instance = instance;
            }
    }

    You can see it implements the IPocoFacade interface. It expects our businessobject that was decorated with the Poco attribute in it's constructor.

    We now just look at the code the Ado.Net team has given us to see how to implement these interfaces.

    The IEntityWithKey for instance, is quite easy:

            #region key
            EntityKey _entityKey = null;

            // Define the EntityKey property for the class.
            EntityKey IEntityWithKey.EntityKey
            {
                get
                {
                    return _entityKey;
                }
                set
                {
                    // Set the EntityKey property, if it is not set.
                    // Report the change if the change tracker exists.
                    if (_changeTracker != null)
                    {
                        _changeTracker.EntityMemberChanging("-EntityKey-");
                        _entityKey = value;
                        _changeTracker.EntityMemberChanged("-EntityKey-");
                    }
                    else
                    {
                        _entityKey = value;
                    }
                }
            }
            #endregion

    Done.

    Since I first want to know if there is interest, I have not implemented relationships and complex types yet.

    Thursday, 21 February 2008 18:59:02 (Romance Standard Time, UTC+01:00)
    Ruurd:

    There's definitely interest on my part and I'm sure Julie Lerman will be interested. I've pinged her on your series.

    Cheers,

    --rj

    See the two items about your project in http://oakleafblog.blogspot.com/2008/02/linq-and-entity-framework-posts-for_19.html
    Thursday, 21 February 2008 19:06:32 (Romance Standard Time, UTC+01:00)
    Thanks Roger, good to know.

    I've made Julie a coordinator of the project, it's good to have her on board.
    Ruurd
    Thursday, 25 November 2010 12:42:24 (Romance Standard Time, UTC+01:00)
    I've made Julie a coordinator of the project, it's good to have her on board.
    ugg boots
    Tuesday, 30 November 2010 08:54:49 (Romance Standard Time, UTC+01:00)
    I've made Julie a coordinator of the project, it's good to have her on board.
    Thursday, 02 December 2010 03:47:09 (Romance Standard Time, UTC+01:00)
    This article was Very helpful. Actually, I am fond of reading online punjabi news. Thanks for writing such a complete ..
    thank you for sharing.
    Comments are closed.