简体   繁体   English

如何在基类中创建对象的克隆?

[英]How do I create clone of object in base class?

I need a method that creates an empty clone of an object in a base class? 我需要一个在基类中创建对象的空克隆的方法吗? For instance: 例如:

public class ChildClass : ParentClass
{
   public ChildClass()
   {
   }
}
public class ParentClass
{
  public SomeMethod()
  {
     // I want to create an instance of the ChildClass here
  }
}

Up until now, we have an abstract method defined in the parent class. 到目前为止,我们在父类中定义了一个抽象方法。 And, all of the child classes implement them. 并且,所有子类都实现它们。 But, the implementation is the same for all, just a different type. 但是,所有实现都相同,只是类型不同。

public class ChildClass : ParentClass
{
   public ChildClass()
   {
   }
   public ParentClass CreateEmpty()
   {
      return new ChildClass();
   }
}
public class ParentClass
{
  public SomeMethod()
  {
     // I want to create an instance of the ChildClass here
     ParentClass empty = CreateEmpty();

  }
  public abstract ParentClass CreateEmpty();
}

Is there any way to do this from the parent class so that I don't have to keep implementing the same logic for each different child class? 有什么办法可以从父类中做到这一点,这样我就不必继续为每个不同的子类实现相同的逻辑? Note that there may be more levels of inheritance (ie ChildChildClass : ChildClass : ParentClass). 注意,可能会有更多级别的继承(即ChildChildClass:ChildClass:ParentClass)。

If using reflection isn't a problem to you, you could do it using Activator class: 如果使用反射对您来说不是问题,则可以使用Activator类来实现:


//In parent class
public ParentClass CreateEmpty()
{
    return (ParentClass)Activator.CreateInstance(this.GetType());
}

This will return empty object of the type you want. 这将返回所需类型的空对象。 Notice that this method does not need to be virtual. 请注意,此方法不必是虚拟的。

On the other hand, I think that your current approach is perfectly fine, few more lines of code aren't so bad. 另一方面,我认为您当前的方法还不错,再多几行代码也不错。

This is somewhat experimental. 这有点实验。 I don't know whether this will lead to a cyclic dependency. 我不知道这是否会导致循环依赖。 Haven't touched C# for some months. 几个月没有接触C#。

public class ParentClass<T> where T : ParentClass<T>, new() { // fixed
    public ParentClass() {
        var x = new T(); // fixed, was T.new()
    }
}

public class ChildClass : ParentClass<ChildClass> {
    public ChildClass() { }
}

Otherwise go for the ReflectionCode by Ravadre. 否则,请使用Ravadre的ReflectionCode。

You can make a deep clone of the object using the binary serializer . 您可以使用二进制序列化程序对对象进行深层克隆。

EDIT: Just noticed the word "empty" next to clone (which I thought was an oxymoron). 编辑:刚注意到克隆(我认为是矛盾的意思)旁边的单词“空”。 Leaving this response up anyhow hoping it will help others that find this question because they are looking to do a regular clone. 不管怎样,不要把这个答案留给别人,因为其他人希望进行常规克隆,这将有助于他们找到这个问题。

I'm using the following pattern. 我正在使用以下模式。

Pros: 优点:

  • This pattern secure the type-safety of cloning in private and public sides of classes. 这种模式确保了在私有和公共类中克隆的类型安全性。
  • The output class will be always correct. 输出类将始终正确。
  • You never forgot override the "clone" method. 您永远不会忘记重写“克隆”方法。 The "MyDerivedClass" never returns another class than the "MyDerivedClass". “ MyDerivedClass”绝不会返回“ MyDerivedClass”之外的其他类。

Cons: 缺点:

  • For one class, you need create one interface and two classes (prototype and final) 对于一个类,您需要创建一个接口和两个类(原型和最终)

Sample: 样品:

// Common interface for cloneable classes.
public interface IPrototype : ICloneable {
    new IPrototype Clone();
}

// Generic interface for cloneable classes.
// The 'TFinal' is finaly class (type) which should be cloned.
public interface IPrototype<TFinal> where TFinal : IPrototype<TFinal> {
    new TFinal Clone();
}

// Base class for cloneable classes.
// The 'TFinal' is finaly class (type) which should be cloned.
public abstract class PrototypeBase<TFinal> : IPrototype<TFinal> where TFinal : PrototypeBase<TFinal> {
    public TFinal Clone() {
        TFinal ret = this.CreateCloneInstance();
        if ( null == ret ) {
            throw new InvalidOperationException( "Clone instance was not created." );
        }

        this.FillCloneInstance( ret );
        return ret;
    }

    // If overriden, creates new cloned instance
    protected abstract TFinal CreateCloneInstance();

    // If overriden, fill clone instance with correct values.
    protected abstract void FillCloneInstance( TFinal clone );

    IPrototype IPrototype.Clone() { return this.Clone(); }
    object ICloneable.Clone() { return this.Clone(); }
}

// Common interface for standalone class.
public interface IMyStandaloneClass : IPrototype<IMyStandaloneClass> {
    string SomeText{get;set;}
    string SomeNumber{get;set;}
}

// The prototype class contains all functionality exception the clone instance creation.
public abstract class MyStandaloneClassPrototype<TFinal> : PrototypeBase<TFinal>, IMyStandaloneClass where TFinal : MyStandaloneClassPrototype<TFinal> {
    public string SomeText {get; set;}
    public int SomeNumber {get; set}

    protected override FillCloneInstance( TFinal clone ) {
        // Now fill clone with values
        clone.SomeText = this.SomeText;
        clone.SomeNumber = this.SomeNumber;
    }
}

// The sealed clas contains only functionality for clone instance creation.
public sealed class MyStandaloneClass : MyStandaloneClassPrototype<MyStandaloneClass> {
    protected override MyStandaloneClass  CreateCloneInstance() {
        return new MyStandaloneClass();
    }
}

public interface IMyExtendedStandaloneClass : IMyStandaloneClass, IPrototype<IMyExtendedStandaloneClass> {
    DateTime SomeTime {get; set;}
}

// The extended prototype of MyStandaloneClassPrototype<TFinal>.
public abstract class MyExtendedStandaloneClassPrototype<TFinal> : MyStandaloneClassPrototype<TFinal> where TFinal : MyExtendedStandaloneClassPrototype<TFinal> {
    public DateTime SomeTime {get; set;}

    protected override FillCloneInstance( TFinal clone ) {
        // at first, fill the base class members
        base.FillCloneInstance( clone );

        // Now fill clone with values
        clone.SomeTime = this.SomeTime;
    }
}

public sealed class MyExtendedStandaloneClass : MyExtendedStandaloneClassPrototype<TFinal> {
    protected override MyExtendedStandaloneClass CreateCloneInstance() {
        return new MyExtendedStandaloneClass 
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从其基类的实例创建新对象? - How do I create a new object from an instance of its base class? 如何为基类创建可选类型注入? - How do I create Optional Type injection for a base class? VisualStudio-当基类在另一个程序集中时,如何为基类函数自动创建访问器? - VisualStudio - How do i automatically create accessors for base class functions when base class is in another assembly? 如何在 Entity Framework Core 中创建由基类和派生类组合而成的复合键 - How do I create composite key which is combination of base class and derived class in Entity Framework Core 如何在C#中创建自定义对象类型类? - How do I create a custom Object type class in C#? 为什么要使用基类引用创建对象? - Why should I want to create an object with base class reference? 如何销毁实例化的游戏对象克隆? - How do I destroy an instantiated game object clone? 如何通过统一检测字符串中的字符来克隆 object? - How do I clone an object from detecting characters in a string in unity? 如何创建实现基本类型通用接口的类的实例 - How do I create instance of class implementing generic interface with base type 如何在 Xunit 中创建一个基础测试 class 来测试接口实现? - How do I create a base test class in Xunit to test interface implementations?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM