Click here to Skip to main content
Click here to Skip to main content

Anonymous Method Serialization

By , 12 Feb 2009
 

Introduction

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));

Code

[Serializable]
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
        else
        {
            MethodInfo method = (MethodInfo)info.GetValue("method", typeof(MethodInfo));

            AnonymousClassWrapper w = 
                (AnonymousClassWrapper)info.GetValue
			("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 ||
            delegate_.Method.DeclaringType
                .GetCustomAttributes(typeof(SerializableAttribute), false).Length > 0) &&
            delegate_ != null)
        {
            info.AddValue("isSerializable", true);
            info.AddValue("delegate", delegate_);
        }

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

    public Delegate Delegate { get { return delegate_; } }

    Delegate delegate_;

    [Serializable]
    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.SetValue(obj,
                        ((SerializeDelegate)info.GetValue
				(field.Name, typeof(SerializeDelegate)))
                            .Delegate);
                //If the field is an anonymous class
                else if(!field.FieldType.IsSerializable)
                    field.SetValue(obj,
                        ((AnonymousClassWrapper)info.GetValue
				(field.Name, typeof(AnonymousClassWrapper)))
                            .obj);
                //otherwise
                else
                    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
					((Delegate)field.GetValue(obj)));
                else if (!field.FieldType.IsSerializable)
                    info.AddValue(field.Name, new AnonymousClassWrapper
				(field.FieldType, field.GetValue(obj)));
                else
                    info.AddValue(field.Name, field.GetValue(obj));
            }
        }

        public Type type; 
        public object obj;
    }
}

History

  • 12th February, 2009: Initial post

License

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
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionwhat do i pass to SerializeDelegate() ?memberserpiccio25 Apr '13 - 0:38 
GeneralUnable to deserializememberpadanfain16 Jun '09 - 6:21 
GeneralRe: Unable to deserializememberchot19 Aug '09 - 11:40 
GeneralA question...protectorMarc Clifton23 Feb '09 - 1:37 
GeneralSerializing/reconstituting delegatesmembersupercat912 Feb '09 - 16:11 
GeneralRe: Serializing/reconstituting delegatesmemberchot13 Feb '09 - 0:27 
GeneralRe: Serializing/reconstituting delegatesmembersupercat913 Feb '09 - 12:21 
GeneralRe: Serializing/reconstituting delegatesmemberchot13 Feb '09 - 14:34 

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

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