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. I have a number of different classes inheriting from Brush and I could pass anyone of them to this method. The inherriting classes all use the same properties in Brush so copying them is not a problem. 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:
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. Subclasses can override it to invoke a suitable constructor.
More concretely, your Brush
class could have the following method:
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.
(This assumes that CopyBrush
is a method of the Brush
class. Otherwise, use internal
or public
visibility for the CreateBrushInstance
method.)
Case 1: All your Brush
-derived classes have a public default constructor, and all properties have public setters.
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; 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);
}
}
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.