简体   繁体   中英

Object Duplication/Serialization problem

I'm having a bit of a problem with a data serialization method I'm using to copy objects. Here's the method:

public static class ObjectDuplicator
        {
            public static T Clone<T>(T source)
            {
                if (!typeof(T).IsSerializable)
                {
                    throw new ArgumentException("the Type must be serializable.", "source");
                }

                if (Object.ReferenceEquals(source, null)) //dont try to serialize a null object
                {
                    return default(T);
                }

                IFormatter formatter = new BinaryFormatter();
                Stream stream = new MemoryStream();
                using (stream)
                {
                    formatter.Serialize(stream, source);
                    stream.Seek(0, SeekOrigin.Begin);
                    return (T)formatter.Deserialize(stream);
                }
            }
        }

The problem is this: when I call this method using the code below

public void AddJob(Job job)
        {
            if (!Jobs.Contains(job))
            {
                Job newcopy = Utilities.ObjectDuplicator.Clone<Job>(job);

                Jobs.Add(newcopy);
            }
        }

it throws this exception:

System.InvalidCastException was unhandled Message=Unable to cast object of type 'KH.CharacterClasses.Freelancer' to type 'KH.CharacterClasses.Job'

Now, the type of job I'm adding is an inherited class from Job, (Freelancer) and the code for those two classes is below

[Serializable]
    public class Job : Ability
    {
        protected JobCommand basecommand1;
        protected JobCommand basecommand2;
        protected JobCommand basecommand3;
        protected JobCommand basecommand4;
        protected JobCommand command1;
        protected JobCommand command2;
        protected JobCommand command3;
        protected JobCommand command4;
        bool mastered;
        protected FFJob job;
        protected string name;
        int level; 

        public FFJob SetJob
        {
            get
            {
                return job;
            }
        }
        public bool Mastered
        {
            get
            {
                return mastered;
            }
        }

        public JobCommand Command1
        {
            get
            {
                return command1;
            }
            set
            {
                command1 = value;
            }
        }

        public JobCommand DefaultCommand1
        {
            get
            {
                return basecommand1;
            }
        }

        public JobCommand Command2
        {
            get
            {
                return command2;
            }
            set
            {
                command2 = value;
            }
        }

        public JobCommand DefaultCommand2
        {
            get
            {
                return basecommand2;
            }
        }

        public JobCommand Command3
        {
            get
            {
                return command3;
            }
            set
            {
                command3 = value;
            }
        }

        public JobCommand DefaultCommand3
        {
            get
            {
                return basecommand3;
            }
        }

        public JobCommand Command4
        {
            get
            {
                return command4;
            }
            set
            {
                command4 = value;
            }
        }

        public JobCommand DefaultCommand4
        {
            get
            {
                return basecommand4;
            }
        }

        public Job(string name, string description, int jobID)
            : base(name, description, jobID, -1, -1, null, null, -1, -1)
        {
        }

        public static bool operator ==(Job job1, Job job2)
        {
            if (System.Object.ReferenceEquals(job1, job2))
                return true;
            if (((object)job1 == null) || ((object)job2 == null))
                return false;
            return (job1.Name == job2.Name && job1.UID == job2.UID);
        }

        public static bool operator !=(Job job1, Job job2)
        {
            return !(job1 == job2);
        }


       // public abstract void CharacterModifier(BaseCharacter character);

       // public abstract void CharacterDemodifier(BaseCharacter character);
    }

    [Serializable]
    public class Freelancer : Job
    {
        public Freelancer()
            : base("Freelancer", "A character not specializing in any class. Can combine the power of all mastered Jobs.", Globals.JobID.ID)
        {
            basecommand1 = JobCommand.Attack;
            basecommand2 = JobCommand.Free;
            basecommand3 = JobCommand.Free;
            basecommand4 = JobCommand.Items;
            command1 = basecommand1;
            command2 = basecommand2;
            command3 = basecommand3;
            command4 = basecommand4;
            job = FFJob.Freelancer;
        }
    }

I'm a bit stumped here because I know the ObjectDuplicator method does work. In fact, this code HAS worked before, but that was on a different computer, and I haven't looked at it in awhile. I'm a little stumped as to why the casting fails here. If someone could help me out with whats wrong thatd be great. If you need more details, just say what you need. I asked this question yesterday, but didn't get a workable answer.

Thanks

Try replacing

return (T)formatter.Deserialize(stream);

with

var result = formatter.Deserialize(stream);
for (Type now = result.GetType(); now != null; now = now.BaseType)
    MessageBox.Show(now.FullName);
return result as T;

What does Clone<T> return? Do you see KH.CharacterClasses.Job in a list of base types? Seems like it's not the base type for Freelancer .

I would never place a return statement into a using clause! Do this instead:

object tClone = null;
using (Stream stream = new MemoryStream()) {
 formatter.Serialize(stream, source);
 stream.Seek(0, SeekOrigin.Begin);
 tClone = formatter.Deserialize(stream);
}
return (T)tClone;

If the exception is still thrown, then your types are indeed incompatible...

Figured out the solution here:

Casting Error when using serialization

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM