如何在没有引用的情况下将基类复制到端类?

how to copy a baseclass to an endclass without reference?

我正在尝试编写一种方法,可以将现有的 class 复制到新的,但不引用源代码 class。
那里有很多示例,但在我的例子中,源对象和目标对象被定义为 baseclass 而它们被创建为 endclass.

我的class是这样的

// my baseclass
public partial class ModelBase
{
    [JsonIgnore]
    public RowStatus Status { get; set; }
}

// one of my endclasses
public class ModelUser: BaseClasses.ModelBase
{
    public int? UserID { get; set; }

    public string UserFirst { get; set; }

    public string UserLastname { get; set; }
}

// and there are many more that derive from ModelBase off course...

我想要的是,在基本表单(所有其他表单都将派生自该表单)中,我可以将现有模型复制到新模型中,而无需引用现有模型。
所以我尝试使用 serializing/deserializing 来做到这一点,效果很好,但前提是你知道确切的类型,而在我的 BaseForm 中我还没有确切的类型,我在那里使用一个声明为 ModelBase 的实例,但是例如,以派生形式创建为 ModelUser。

换句话说,我有一个像这样的基本形式

public partial class FormMVBaseDetail
{
    protected ModelBase model = null;
    protected ModelBase _originalModel = null;
    ...

    private void FormMVBaseDetail_Shown(object sender, EventArgs e)
    {
        _originalModel = CloneModel(model);
    }

    protected ModelBase CloneModel(ModelBase model)
    {
        string json = JsonConvert.SerializeObject(model);
        return JsonConvert.DeserializeObject<ModelBase>(json);
    }
}

public partial class FormMVBaseUser : FormMVBaseDetail
{
    model = new ModelUser();
    ...
    // somewhere in the code some properties of model could change...

    private void button1_Click(object sender, EventArgs e)
    {
        // Now I would like that _originalModel is an exact copy of model
        // So _originalModel should be of type ModelUser, not ModelBase
        // How to achieve that without additional code in FormMBaseUser ?
     
        if (_originalModel.UserFirst != model.UserFirst)
        { // do something }
    }
}

第一次尝试是这样

public ModelBase CloneModel(ModelBase model)
{
    string json = JsonConvert.SerializeObject(model);
    return JsonConvert.DeserializeObject<ModelBase>(json);
}

这有一个问题,尽管参数 model 被创建为 new ModelUser(),但反序列化会使它成为一个 ModelBase,它只有一个 public 属性, 状态。

如果我这样做,那么它会起作用,但仅适用于 ModelUser

public ModelBase CloneModel(ModelBase model)
{
    string json = JsonConvert.SerializeObject(model);
    return JsonConvert.DeserializeObject<ModelUser>(json);
}

这在基本形式中没有用。
所以接下来我尝试的是这个

public object CloneModel(ModelBase model)
{
    string json = JsonConvert.SerializeObject(model);
    return JsonConvert.DeserializeObject<object>(json);
}

我的想法是像这样使用它

ModelBase _originalModel = null;
_originalModel = (ModelBase)CloneModel(CurrentModel);

但由于某些原因,它总是反序列化为 Newtonsoft.Json.Linq.JObject 而不是 object,所以这对我也不起作用。

我怎样才能做到这一点?

我已经阅读了这个链接,但他们没有进一步帮助我

How do I use reflection to call a generic method?
Passing just a type as a parameter in C#
How can I use an expression tree to call a generic method when the Type is only known at runtime?

您可以使用 JsonConvert.DeserializeObject()

的非通用版本

第一个参数是字符串,第二个是类型。

所以你的克隆函数将是这样的:

public object CloneModel(ModelBase model)
{
    string json = JsonConvert.SerializeObject(model);
    return JsonConvert.DeserializeObject(json, model.GetType());
}

Ygalbel 答案的通用版本是这样的:

public partial class FormMVBaseDetail<T> where T : ModelBase
{
    protected T _model;
    protected T _originalModel;

    public T CloneModel(T model)
    {
       var json = JsonConvert.SerializeObject(model);
       return JsonConvert.DeserializeObject<T>(json);
    }
}

是否希望基础 class 通用将取决于您的需要。

用法:

public partial class FormMVBaseUser : FormMVBaseDetail<ModelUser>
{
    _model = new ModelUser();
    // Other code as before