15.02.2015 Views

C# 4 and .NET 4

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

630 ❘ ChaPTer 23 system.trAnsActiOns<br />

private Transaction currentTransaction;<br />

internal ResourceManager(Transactional parent, Transaction tx)<br />

{<br />

this.parent = parent;<br />

Value = DeepCopy(parent.liveValue);<br />

currentTransaction = tx;<br />

}<br />

public T1 Value { get; set; }<br />

code snippet CustomResource/ResourceManager.cs<br />

Because the temporary value may change within the transaction, the live value of the wrapper class may<br />

not be changed within the transaction. When creating a copy with some classes, it is possible to invoke<br />

the Clone() method that is defined with the ICloneable interface. However, as the Clone() method is<br />

defined, it allows implementations to create either a shallow or a deep copy. If type T contains reference<br />

types <strong>and</strong> implements a shallow copy, changing the temporary value would also change the original value.<br />

This would be in conflict with the isolation <strong>and</strong> consistency features of transactions. Here, a deep<br />

copy is required.<br />

To do a deep copy, the method DeepCopy() serializes <strong>and</strong> deserializes the object to <strong>and</strong> from a stream.<br />

Because in <strong>C#</strong> 4 it is not possible to define a constraint to the type T indicating that serialization is required,<br />

the static constructor of the class Transactional checks if the type is serializable by checking the<br />

property IsSerializable of the Type object.<br />

static ResourceManager()<br />

{<br />

Type t = typeof(T1);<br />

Trace.Assert(t.IsSerializable, "Type " + t.Name +<br />

" is not serializable");<br />

}<br />

private T1 DeepCopy(T1 value)<br />

{<br />

using (MemoryStream stream = new MemoryStream())<br />

{<br />

BinaryFormatter formatter = new BinaryFormatter();<br />

formatter.Serialize(stream, value);<br />

stream.Flush();<br />

stream.Seek(0, SeekOrigin.Begin);<br />

}<br />

}<br />

return (T1)formatter.Deserialize(stream);<br />

The interface IEnlistmentNotification is implemented by the class ResourceManager. This is the<br />

requirement for enlisting with transactions.<br />

The implementation of the Prepare() method just answers by invoking Prepared() with<br />

preparingEnlistment. There should not be a problem assigning the temporary value to the live value, so<br />

the Prepare() method succeeds. With the implementation of the Commit() method, the Commit() method<br />

of the parent is invoked, where the variable liveValue is set to the value of the ResourceManager that<br />

is used within the transaction. The Rollback() method just completes the work <strong>and</strong> leaves the live value<br />

where it was. With a volatile resource, there is not a lot you can do in the InDoubt() method. Writing a log<br />

entry could be useful:<br />

public void Prepare(PreparingEnlistment preparingEnlistment)<br />

{<br />

preparingEnlistment.Prepared();<br />

}<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!