[英]How do I write a general method to copy instances of classes that all inherit from the same abstract base class?
I want to copy the details of one instance of a brush to a new instance as per the code below: 我想按照以下代码将一个画笔实例的详细信息复制到一个新实例:
private static Brush CopyBrush(Brush b)
{
Brush b1 = new Brush();
// code to copy settings from b to b1
return b1;
}
My difficulty is that Brush is an abstract class so I cannot instantiate it. 我的困难是Brush是一个抽象类,因此我无法实例化它。 I have a number of different classes inheriting from Brush and I could pass anyone of them to this method.
我有许多不同的类继承自Brush,可以将其中的任何一个都传递给此方法。 The inherriting classes all use the same properties in Brush so copying them is not a problem.
继承类都在Brush中使用相同的属性,因此复制它们不是问题。 The return can be cast back to the inheriting type at the call source.
可以在调用源将返回值强制转换回继承类型。
If all of your derived classes are guaranteed to have a constructor with a certain signature, eg without any arguments, you can instantiate the respective subtype based on its Type
instance: 如果保证所有派生类都具有带有特定签名的构造函数(例如,不带任何参数),则可以基于其子
Type
实例实例化各自的子Type
:
Brush b1 = (Brush)Activator.CreateInstance(b.GetType());
If that cannot be guaranteed, you'll need to introduce a virtual method in your Brush
class to create a new instance of the current class. 如果不能保证这一点,则需要在
Brush
类中引入虚拟方法来创建当前类的新实例。 Subclasses can override it to invoke a suitable constructor. 子类可以重写它以调用合适的构造函数。
More concretely, your Brush
class could have the following method: 更具体地说,您的
Brush
类可以具有以下方法:
protected virtual Brush CreateBrushInstance()
{
return (Brush)Activator.CreateInstance(GetType());
}
In any derived class that requires different constructor arguments, override this method and call the Activator.Create(Type, object[])
method with the appropriate argument values. 在需要不同构造函数参数的任何派生类中,重写此方法并使用适当的参数值调用
Activator.Create(Type, object[])
方法 。
(This assumes that CopyBrush
is a method of the Brush
class. Otherwise, use internal
or public
visibility for the CreateBrushInstance
method.) (这假定
CopyBrush
是Brush
类的方法。否则,对CreateBrushInstance
方法使用internal
或public
可见性。)
Case 1: All your Brush
-derived classes have a public default constructor, and all properties have public setters. 情况1:您所有从
Brush
派生的类都有一个公共的默认构造函数,而所有属性都有一个公共的setter。
In this case, one generic method should suffice: 在这种情况下,一个通用方法就足够了:
static TBrush Copy<TBrush>(this TBrush brush) where TBrush : Brush, new()
{
return new TBrush() // <- possible due to the `new()` constraint ^^^
{
TypeOfHair = brush.TypeOfHair,
NumberOfHairs = brush.NumberOfHairs,
…
};
}
Case 2: One or more of the above preconditions are not met; 情况2:不满足上述一个或多个前提条件; ie there is no public default constructor, or at least one property is not publicly settable.
也就是说,没有公共默认构造函数,或者至少一个属性是不可公开设置的。
You can use this pattern: 您可以使用以下模式:
abstract class Brush
{
protected abstract Brush PrepareCopy();
// replacement for public default ctor; prepares a copy of the derived brush
// where all private members have been copied into the new, returned instance.
public Brush Copy()
{
// (1) let the derived class prepare a copy of itself with all inaccessible
// members copied:
Brush copy = PrepareCopy();
// (2) let's copy the remaining publicly settable properties:
copy.TypeOfHair = this.TypeOfHair;
copy.NumberOfHairs = this.NumberOfHairs;
return copy;
}
}
sealed class FooBrush : Brush
{
public FooBrush(int somethingPrivate)
{
this.somethingPrivate = somethingPrivate;
// might initialise other members here…
}
private readonly int somethingPrivate;
protected override Brush PrepareCopy()
{
return new FooBrush(somethingPrivate);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.