Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Delegate Mapper

When I was in Holland Jelle Hissink pointed out a quick easy piece of code that is extremely useful in many scenarios I have seen in the past. It maps delegates from Base classes to Derived classes. Previously working with messaging I used the Handles<T> methodology which has since become popular in both MassTransit and nServiceBus. It allowed you to use typed message handlers as opposed to having to write handlers that used the base class then casted to the specific type. This code does the same but using delegates which is pretty slick and can be used in an aggregate root base class quite easily to handle the mapping of events to methods that apply them internally (you can also use it for event/command handlers if you don’t want to use an existing framework such as nServiceBus or MassTransit). Here is the code.

public class DelegateAdjuster
{
    public static Action<BaseT> CastArgument<BaseT, DerivedT>(Expression<Action<DerivedT>> source) where DerivedT : BaseT
    {
        if (typeof(DerivedT) == typeof(BaseT))
        {
            return (Action<BaseT>)((Delegate)source.Compile());

        }
        ParameterExpression sourceParameter = Expression.Parameter(typeof(BaseT), "source");
        var result = Expression.Lambda<Action<BaseT>>(
            Expression.Invoke(
                source,
                Expression.Convert(sourceParameter, typeof(DerivedT))),
            sourceParameter);
        return result.Compile();
    }
}

 

Simple, and slick.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

15 Responses to Delegate Mapper

  1. Greg says:

    Roy,

    There are a few ways.

    Note I dont use this way anymore … see the simple cqrs example for another way :)

    You can manually register, or you can use dynamic reflection binding by convention.

  2. Roy says:

    I do wonder how you were accomplishing this mapping prior to this Delegate Mapper.

  3. Roy says:

    Ah… I had confused this code (somehow) with trying to register derived entity private methods to the base aggregate root.

    This delegate mapper is very handy for registering methods in a bus.

    thanks

  4. Roy says:

    Whacky lookin’ code.

    When deserializing an Aggregate Root (AR) though, does this code have to be run against the AR again?

    If it doesn’t have to be run after each deserialization, I definitly need to understand how that’s possible.

  5. zuken21@yahoo.com says:

    Sorry for reply on wrong article!

    TCP: Buffer Management
    I cant download buffer management from the link codebetter.com/…/entry181822.aspx

    It’s a useful code for learning, please reupload it again

    Thanks

  6. pete w says:

    love it! thank you

  7. MarcinNajder says:

    Nice code!

    I think its all about covariance and contravariance of generic delegates. We don’t have to wait for .Net 4.0 (C#4.0). Look at this:

    public static class Extensions
    {
    public static Func
    ConvertTo
    (this Func del)
    where TR : TR_
    {
    return Delegate.CreateDelegate(typeof (Func
    ), del.Target, del.Method)
    as Func
    ;
    }

    public static Action ConvertTo(this Action del)
    where T1_ : T1
    {
    return Delegate.CreateDelegate(typeof (Action), del.Target, del.Method)
    as Action
    ;
    }

    public static Func ConvertTo(this Func del)
    where TR : TR_
    where T1_ : T1
    {
    return Delegate.CreateDelegate(typeof(Func), del.Target, del.Method)
    as Func
    ;
    }

    public static Func ConvertTo(this Func del)
    where TR : TR_
    where T1_ : T1
    where T2_ : T2
    {
    return Delegate.CreateDelegate(typeof(Func), del.Target, del.Method)
    as Func
    ;
    }
    }

    // covariance
    Func func1 = () => new Person() { Name= “person” };
    Func func2 = () => new Student() {Name = “student”};

    func1 = func2.ConvertTo();

  8. matt says:

    Brain block here – could you provide an example usage of this? I understand the mechanics, just having trouble following how you would put it to use.

  9. Please help me to CODE BETTER and provide a usage sample.

  10. MarcinNajder says:

    Nice code!

    I think its all about covariance and contravariance of generic delegates. We don’t have to wait for .Net 4.0 (C#4.0). Look at this:

    public static class Extensions
    {
    public static Func
    ConvertTo
    (this Func del)
    where TR : TR_
    {
    return Delegate.CreateDelegate(typeof (Func
    ), del.Target, del.Method)
    as Func
    ;
    }

    public static Action ConvertTo(this Action del)
    where T1_ : T1
    {
    return Delegate.CreateDelegate(typeof (Action), del.Target, del.Method)
    as Action
    ;
    }

    public static Func ConvertTo(this Func del)
    where TR : TR_
    where T1_ : T1
    {
    return Delegate.CreateDelegate(typeof(Func), del.Target, del.Method)
    as Func
    ;
    }

    public static Func ConvertTo(this Func del)
    where TR : TR_
    where T1_ : T1
    where T2_ : T2
    {
    return Delegate.CreateDelegate(typeof(Func), del.Target, del.Method)
    as Func
    ;
    }
    }

    // covariance
    Func func1 = () => new Person() { Name= “person” };
    Func func2 = () => new Student() {Name = “student”};

    func1 = func2.ConvertTo();

  11. No Body says:

    @Nick Palladinos, are they the same as Greg posted above?

  12. Nick,
    nice improvement, the obvious step πŸ˜‰

  13. Can you provide a usage sample please?

  14. tobi says:

    was about to post just that πŸ˜‰

  15. public static Action CastArgument(Action source)
    where DerivedT : BaseT
    {
    return baseValue => source((DerivedT) baseValue);
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>