0:00 / 9:05 So all this business of having to implement special copy logic in each of the types is really tedious

and we want to get away from it.

And there is a way to get all of this functionality automatically because if you take a serializer and

you serialize your object, the serializer should serialize the entire tree.

So that kind of takes care of the problem.

And now all we have to do is implement the actual methods for performing both serialization.

That’s when you take the object and you serialize it to some format like binary or XML.

It doesn’t really matter and then you deserialize it, thereby making a full deep copy.

So that’s how the prototype pattern is actually done in the real world.

And that’s what we’re going to take a look at in this clip.

Okay, so here we want to perform a deep copy and we don’t want some sort of I prototype interface or

maybe we do, but maybe there is more than one way of doing it.

In actual fact, we can implement some sort of deep copy mechanic on any type T without using interfaces,

because interfaces mean that we have to find every single object participating in the serialization

and tag it with this marker interface.

How about not doing that?

So I’m going to get rid of the I prototype here.

I’m going to get rid similarly of I prototype here and we’re going to simply write a bunch of extension

methods which work on any kind of object.

So let me build a new class.

It’s going to be a static class called extension methods, and I’m going to build an extension method

for deep copying using, let’s say, the binary serializer.

So we’re going to be using the binary formatter.

So I’m going to say public static T, So T is the type that’s being copied.

The actual method is going to be called deep copy.

So nobody has any illusions as to what it does.

It’s a template method with a type argument.

T and this takes T self, so it’s an extension method on any type effectively.

And what you have to do here is you have to serialize and then deserialize the object, thereby making

a full, proper, deep copy of it.

So we’ll say var stream equals new memory stream because it’s going to be stored in memory.

We’re not going to store the object in serialized form on disk or anything like that, and then we’ll

use the binary formatter.

So var formatter.

Formatter like so equals.

New binary formatter.

So that’s what’s going to be doing the serialization.

I have to import the appropriate namespace in actual fact.

And then here’s what we do.

We take the formatter and we serialize.

So we serialize the object into the stream.

So the stream is our memory stream and the object we are serializing is self.

That’s what we are calling the extension method on.

So self goes in here.

So now what’s happening is we’ve initialized the memory stream with a serialized version of the object

and now we need to get it out.

So to get it out, we first of all have to rewind the stream back to the beginning.

So this is done using seek.

So we say stream dot seek with the value of zero, that’s the offset.

So we get to the beginning and we say seek origin dot begin.

So it’s the offset of zero from the beginning.

That’s how we get to the starting point.

And then of course we make a copy.

So we say object copy equals formatter dot deserialize.

And then we go into that memory stream that we have and we take the data from there and deserialize

it into a brand new object.

Then we close the stream like so, and then we return the object, which is copy and we need to cast

it to T so we simply cast it to T like that.

So now we have an extension method called Deep copy, which works on just about anyone, to be honest,

any object that we might have.

So coming back to our example here, and I’m going to make it more complete by actually setting Jane’s

name for a change.

So what you would do here is you would say deep copy.

And that’s the that’s the implementation that we have already.

But this time around, I’m going to get rid of the deep copies inside person itself.

So we’re only going to have the extension method to work with.

And the same goes for address as well.

We don’t need them anymore because now we have this universal mechanism.

So now the deep copy that we’re calling this deep copy here.

If I go to definition, it goes into our extension methods.

So let’s set also Jane’s name.

So I’ll say Jane dot names at zero equals Jane and we’ll execute this once again and see what we actually

get.

And we get an exception.

So I’m pretty sure you know why this is, but this is yet another problem.

This is yet another concern.

Remember, we we kind of got away from implementing the interface everywhere and we said, yes, we

don’t have to go through the hierarchy anymore and modify every single class.

Well, guess what?

There are additional problems here.

And the additional problem has to do with the fact that every type that you try to serialize using the

binary formatter has to be serializable.

So it has to be serializable here.

But also every member has to be serializable as well, which means if you go down here, that has to

be serializable as well.

So let’s try this again.

And now everything is working correctly.

We change John to Jane and we change the house number and everything is fine.

So the caveat here is going through every single class, but we can get away from this as well because

nobody’s really forcing you to use binary serialization.

Sure, it’s fast, but there are other ways and one of those ways is deep copying using some other formatter,

like, for example, XML serialization.

So in this case, what we can do is we can make another extension method.

So I’ll have public static T and it’s going to be deep copy XML.

We’re going to be using the XML serializer.

So once again it’s a generic on T, it takes T self or in actual fact it’s an extension on any type

T, and here we just make an XML serializer.

So var s equals new XML serializer for the type of T, and then of course we serialize the XML.

So once again we need the memory stream though.

So let’s actually put it in a using this time using var equals new memory stream memory stream like

so.

So we’re going to be doing a using statement which will close the stream automatically on dispose.

So we serialize the object called self to the stream.

And then of course once again we take the memory stream, we set its position to zero.

So set position to zero.

That’s an alternative to calling C does exactly the same thing.

And then we return miss or s rather dot Deserialize So we take the XML serialize and deserialize whatever

is in the memory stream.

And of course we have to cast it to the object of type T So this is doing.

Being using the XML serializer.

And this gets us away from that final requirement of having that pesky serializable all over the place.

So let’s see if this works.

Okay.

So I got rid of serializable everywhere and I’m going to change this to deep copy XML like so and actually

execute and oops, here is another problem.

So one of the requirements of the XML serializer is that you have to have parameterless constructors

on each of your objects.

And we don’t because I explicitly specified the objects to be constructed out of the initializing properties

that we want to assign.

So if I generate an empty constructor on each of these.

Then everything should be fine.

And we now have the correct behavior.

So the takeaway from this, and I’m sorry to say there are requirements which need to be satisfied by

different serializers or by they need to be satisfied by your classes for different serializers.

And if you satisfy those requirements, then yes, you can use different forms of serialization, but

you are going to encounter problems like this.

So you are serializing a large object chain and then all of a sudden one of the objects doesn’t have

a default constructor and that’s it.

That’s the XML serialization out of the window.

So you’re welcome to sort of experiment with other different types of serializers looking for the one

which suits your needs.

But I’ve shown you both two implementations that you can use as well as some of the problems that you

might encounter.

Play Play Play Play Play Stop Start Play information alert