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.
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.
I do wonder how you were accomplishing this mapping prior to this Delegate Mapper.
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
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.
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
love it! thank you
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
ConvertTo
(this Func
del)
), del.Target, del.Method)
;
{
public static Func
where TR : TR_
{
return Delegate.CreateDelegate(typeof (Func
as Func
}
public static Action ConvertTo(this Action del)), del.Target, del.Method) ;
where T1_ : T1
{
return Delegate.CreateDelegate(typeof (Action
as Action
}
public static Func ConvertTo(this Func del)), del.Target, del.Method) ;
where TR : TR_
where T1_ : T1
{
return Delegate.CreateDelegate(typeof(Func
as Func
}
public static Func ConvertTo(this Func del)), del.Target, del.Method) ;
where TR : TR_
where T1_ : T1
where T2_ : T2
{
return Delegate.CreateDelegate(typeof(Func
as Func
}
}
// covariance func1 = () => new Person() { Name= “person” }; func2 = () => new Student() {Name = “student”};
Func
Func
func1 = func2.ConvertTo();
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.
Please help me to CODE BETTER and provide a usage sample.
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
ConvertTo
(this Func
del)
), del.Target, del.Method)
;
{
public static Func
where TR : TR_
{
return Delegate.CreateDelegate(typeof (Func
as Func
}
public static Action ConvertTo(this Action del)), del.Target, del.Method) ;
where T1_ : T1
{
return Delegate.CreateDelegate(typeof (Action
as Action
}
public static Func ConvertTo(this Func del)), del.Target, del.Method) ;
where TR : TR_
where T1_ : T1
{
return Delegate.CreateDelegate(typeof(Func
as Func
}
public static Func ConvertTo(this Func del)), del.Target, del.Method) ;
where TR : TR_
where T1_ : T1
where T2_ : T2
{
return Delegate.CreateDelegate(typeof(Func
as Func
}
}
// covariance func1 = () => new Person() { Name= “person” }; func2 = () => new Student() {Name = “student”};
Func
Func
func1 = func2.ConvertTo();
@Nick Palladinos, are they the same as Greg posted above?
Nick,
nice improvement, the obvious step
Can you provide a usage sample please?
was about to post just that
public static Action CastArgument (Action source)
where DerivedT : BaseT
{
return baseValue => source((DerivedT) baseValue);
}