使用序列化时出现转换错误

4

我之前问过这个问题,但没有得到可用的答案。基本上,由于无效的转换异常,我无法使我的对象复制方法起作用。但是,在复制方法之外,我可以很好地进行类型转换。

以下是复制方法:

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

问题是这样的:当我使用下面的代码调用此方法时
public void AddJob(Job job)
{
    if (!Jobs.Contains(job))
    {
        Job newcopy = Utilities.ObjectDuplicator.Clone<Job>(job);

        Jobs.Add(newcopy);
    }
}

它抛出了这个异常:

System.InvalidCastException未处理 消息=无法将类型为“KH.CharacterClasses.Freelancer”的对象强制转换为类型“KH.CharacterClasses.Job”

现在,我要添加的工作类型是从Job继承的类(自由职业者),下面是这两个类的代码:

[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;
    }
}

我真的不知道问题出在哪里。就像我说的,除了这个方法之外,转换都很正常,而且我知道这段代码以前是可以工作的。有什么想法吗?

谢谢


序列化代码看起来没问题。我很确定我在其他地方也做了同样的事情。我会看一下。 - Daniel James Bryars
是的,我对派生类型进行了序列化,并在反序列化时将其转换为基础类型。你的问题看起来非常奇怪,我不理解。很抱歉我无法提供帮助。 - Daniel James Bryars
你能提供完整的异常堆栈跟踪吗?还有内部异常。最后,尝试将对 T 的转换移到另一行,以便您可以检查该对象。 - leppie
2个回答

1
我搞明白了。在某个时候,我把它编译成一个.dll文件以便在另一个项目中引用。我忘记从bin目录中删除.dll文件,所以程序是从dll中加载我的类,而不是从代码的新版本中加载。我意识到这一点是在尝试直接复制同种类型对象后发现它同时引用了.dll和.exe中的内容。删除.dll文件解决了问题。我太傻了。

0
如果您只想要复制而不是序列化,为什么不实现IClonable呢?每种类型都有一个受保护的方法叫做MemberwiseClone,可以极大地简化所涉及的工作。

1
我认为只需要一个复制对象的方法比每种类型都有一个方法更容易。 - Megatron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接