PostSharpUndo/RedoAssigning Recorders Manually
Open sandboxFocusImprove this doc

Assigning Recorders Manually

By default, all recordable objects are attached to the global Recorder exposed on the DefaultRecorder property. There is nothing you have to do to make this happen. There may be circumstances where you want to create and assign your own recorder to the undo/redo process. There are two different ways that you can accomplish this.

Overriding the default RecorderProvider

By default, the RecordableAttribute aspect attaches an object to a Recorder as soon as its constructor exits. To determine which Recorder should be used, the aspect uses the RecorderProvider service. By default, this service always serves the global instance that is also exposed on the DefaultRecorder property.

You can override this automatic assignment to inject your own RecorderProvider to into the process.

To use a custom RecorderProvider:

  1. Create a class inherited from the RecorderProvider class.

  2. Implement the chaining constructor. The RecorderProvider that you inherited from requires a RecorderProvider as a constructor parameter. This constructor parameter facilitates the chain of responsibility for providers that can be run when a Recorder is requested. To keep the chain of responsibility intact your custom RecorderProvider will need to accept a RecorderProvider in its constructor and pass that to the base constructor.

  3. Override the GetRecorderCore(Object) method.

  4. Insert an instance of your custom RecorderProvider class into the chain of responsibility by assigning it to the RecorderProvider.

    RecordingServices.RecorderProvider = new MyProvider(RecordingServices.RecorderProvider);
    
Note

RecorderProvider is a chain of responsibility. As such, if a GetRecorderCore(Object) method returns null then the chain will move on to the next RecorderProvider and attempt to get a Recorder to use.

By overriding the default RecorderProvider you are able to assign a custom Recorder across the entire application.

Example

public class ThreadStaticRecorderProvider : RecorderProvider
{                
  private static Recorder _recorder;

  public ThreadStaticRecorderProvider(RecorderProvider next) : base(next)
  {
  }

  public Recorder GetRecorderImpl(object obj)
  {
    if ( _recorder == null )
    {
       _recorder = new Recorder();
    }

    return _recorder;
  }
}

Attaching a recorder manually

The second way that you can add a Recorder to objects is to manually assign them when, and where, they are needed.

To manually assign a Recorder to an object:

  1. Set the AutoRecord property to false for that class.

    [Recordable(AutoRecord = false)]
    public class Invoice
    {
    }
    
    Note

    By disabling AutoRecord you are telling the RecordingServices that this object should not be included in recordings unless the recording is explicitly declared in your code.

  2. Create a new instance of a Recorder and attach the object to it using the Attach(Object) method.

    var invoice = new Invoice();
    
    var recorder = new Recorder();
    recorder.Attach(invoice);
    

    You can then use the Detach(Object) method to remove the Recorder from the object in question.

Note

An object must always have the same Recorder as its parent has unless the parent has no Recorder assigned. Because of this, whenever a Recorder is assigned to an object, all of the child objects will have that same Recorder assigned to them. However, if you detach a child object from its parent the child object's assigned Recorder will not be detached. For more information about parent-child relationships, see Parent/Child, Visitor and Disposable.