Click here to Skip to main content
12,550,033 members (47,866 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


20 bookmarked

Anonymous Method Serialization

, 12 Feb 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Anonymous method serialization


Anonymous methods cannot be serialized in C# (unless they do not reference any stack variables). The most simple solution would be to add the [Serializable] attribute to the anonymous class generated for the method, but since this is (as far as I know) not possible yet, we have to use this "hack".

This is an updated version of Jeremy Thomas' version that can be found here, with the improvement that this also supports nested delegates, and any delegate.

Please note that this code is not very well tested.  Also note that anything you reference inside the anonymous method also gets serialized, including this. This means that, if you serialize a delegate referencing this and then deserialize it again and run it, then this will refer to a new copy of the object.

Using the Code 

formater.Serialize(stream, new SerializeDelegate(myDelegate));


public class SerializeDelegate : ISerializable
    internal SerializeDelegate(Delegate delegate_)
        this.delegate_ = delegate_;

    internal SerializeDelegate(SerializationInfo info, StreamingContext context)
        Type delType = (Type)info.GetValue("delegateType", typeof(Type));

        //If it's a "simple" delegate we just read it straight off
        if (info.GetBoolean("isSerializable"))
            this.delegate_ = (Delegate)info.GetValue("delegate", delType);

        //otherwise, we need to read its anonymous class
            MethodInfo method = (MethodInfo)info.GetValue("method", typeof(MethodInfo));

            AnonymousClassWrapper w = 
			("class", typeof(AnonymousClassWrapper));

            delegate_ = Delegate.CreateDelegate(delType, w.obj, method);

    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        info.AddValue("delegateType", delegate_.GetType());

        //If it's an "simple" delegate we can serialize it directly
        if ((delegate_.Target == null ||
                .GetCustomAttributes(typeof(SerializableAttribute), false).Length > 0) &&
            delegate_ != null)
            info.AddValue("isSerializable", true);
            info.AddValue("delegate", delegate_);

        //otherwise, serialize anonymous class
            info.AddValue("isSerializable", false);
            info.AddValue("method", delegate_.Method);
                new AnonymousClassWrapper
		(delegate_.Method.DeclaringType, delegate_.Target));

    public Delegate Delegate { get { return delegate_; } }

    Delegate delegate_;

    class AnonymousClassWrapper : ISerializable
        internal AnonymousClassWrapper(Type bclass, object bobject)
            this.type = bclass;
            this.obj = bobject;

        internal AnonymousClassWrapper(SerializationInfo info, StreamingContext context)
            Type classType = (Type)info.GetValue("classType", typeof(Type));
            obj = Activator.CreateInstance(classType);

            foreach (FieldInfo field in classType.GetFields())
                //If the field is a delegate
                if (typeof(Delegate).IsAssignableFrom(field.FieldType))
				(field.Name, typeof(SerializeDelegate)))
                //If the field is an anonymous class
                else if(!field.FieldType.IsSerializable)
				(field.Name, typeof(AnonymousClassWrapper)))
                    field.SetValue(obj, info.GetValue(field.Name, field.FieldType));

        void ISerializable.GetObjectData
		(SerializationInfo info, StreamingContext context)
            info.AddValue("classType", type);

            foreach (FieldInfo field in type.GetFields())
                //See corresponding comments above
                if (typeof(Delegate).IsAssignableFrom(field.FieldType))
                    info.AddValue(field.Name, new SerializeDelegate
                else if (!field.FieldType.IsSerializable)
                    info.AddValue(field.Name, new AnonymousClassWrapper
				(field.FieldType, field.GetValue(obj)));
                    info.AddValue(field.Name, field.GetValue(obj));

        public Type type; 
        public object obj;


  • 12th February, 2009: Initial post


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Fredrik Norén
CEO Keldyn Interactive
Sweden Sweden
No Biography provided

You may also be interested in...


Comments and Discussions

Questionwhat do i pass to SerializeDelegate() ? Pin
serpiccio25-Apr-13 0:38
memberserpiccio25-Apr-13 0:38 
GeneralUnable to deserialize Pin
padanfain16-Jun-09 6:21
memberpadanfain16-Jun-09 6:21 
GeneralRe: Unable to deserialize Pin
chot19-Aug-09 11:40
memberchot19-Aug-09 11:40 
GeneralA question... Pin
Marc Clifton23-Feb-09 1:37
protectorMarc Clifton23-Feb-09 1:37 
GeneralSerializing/reconstituting delegates Pin
supercat912-Feb-09 16:11
membersupercat912-Feb-09 16:11 
GeneralRe: Serializing/reconstituting delegates Pin
chot13-Feb-09 0:27
memberchot13-Feb-09 0:27 
GeneralRe: Serializing/reconstituting delegates Pin
supercat913-Feb-09 12:21
membersupercat913-Feb-09 12:21 
GeneralRe: Serializing/reconstituting delegates Pin
chot13-Feb-09 14:34
memberchot13-Feb-09 14:34 
Well first of, maybe RPC wasn't quite the right word since actually, in most of my calls I don't expect a result. If you do need to handle a result, you can simply send it back with a new anonymous delegate (this is why it supports nested delegates):
Send(ep1, idOfep1Object, (ep1Object) => 
   var result = ep1Object.DoSomeWork();
   Send(ep2, idOfep2Object, (ep2Object) => ep2Object.HandleResultOfWork(result));
And I make sure I never reference the this pointer, but rather supply the object as an argument to the delegate. Also, I need to supply an id to the object, which is used on the receiving end to look up to the object and supply it as an argument to the delegate. In my version of SerializeDelegate, I actually have some code which detects a this references and throws an exception.

Just to clarify; normally in network communication (which is for what I am using this) you send messages, and normally the first byte or string or whatever decides what should be done and after that follows some arguments. This is basically the same thing(a method and arguments) just that I don't specify the protocol explicitly. Also this way makes it a bit easier (at least for me) to think about it, you can see what will happen right there.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.161021.1 | Last Updated 12 Feb 2009
Article Copyright 2009 by Fredrik Norén
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid