Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dcastro/mementocontainer


https://github.com/dcastro/mementocontainer

Last synced: 26 days ago
JSON representation

Awesome Lists containing this project

README

        

# MementoContainer

MementoContainer is an alternative approach to the [Memento design pattern](http://paginas.fe.up.pt/~aaguiar/as/gof/hires/pat5ffso.htm).

It is a lightweight utility that takes a snapshot of your objects' state so that you can easily rollback to a previous state when recovering from errors.

This approach, like the original one, promotes highly decoupled systems and preserves encapsulation boundaries while leveraging C#'s awesomeness
(e.g., reflection, attributes, lambda expression analysis, dynamic typing) to avoid polluting your code base with Memento types.

Besides, taking a snapshot of an object's state isn't always a trivial task.
If you have a big dependency graph, then you will probably have to perform tedious deep cloning of your objects.
MementoContainer does all that for you - and more.

```csharp
var memento = Memento.Create()
.Register(article);

try
{
ArticleFormatter.Format(article);
}
catch(FormattingException)
{
memento.Rollback(); //Et voilà!
}

```

## Getting started

### Registering objects

The first step is to annotate your model's properties with the `MementoProperty` and/or `MementoCollection` attributes, so that the memento will know which properties it will need to watch.

```csharp
public class Magazine
{
[MementoProperty]
public string Title { get; set; }

[MementoCollection]
public IList Articles { get; set; }
}
```

In order to preserve encapsulation, these properties can have any access modifiers (private, public, protected) and even be static.
And if the class `Article` also happens to have annotated properties, those will be registered as well!

Alternatively, you may also use the `MementoClass` attribute on your classes.
This way, all your object's properties/collections will be recorded.
```csharp
[MementoClass]
public class Article
{
public string Title { get; set; }
public string Author { get; set; }
}
```

The Memento object exposes a [fluent interface](http://www.martinfowler.com/bliki/FluentInterface.html) so that you can easily register all your objects with the container.

```csharp
var magazine1 = new Magazine
{
Title = "Draft",
Articles = new List
{
new Article("Draft", "DCastro")
}
};

var memento = Memento.Create()
.Register(magazine1)
.Register(magazine2)
.Register(publisher);
```

Now you can freely act upon your objects and if anything goes wrong, just rollback!

```csharp
try
{
magazine1.Name = "State of emergency declared";
magazine1.Articles.Clear();
db.Save(magazine1);
}
catch(DBException)
{
//The magazine will be renamed back to "Draft"
//and the article authored by "DCastro" will be re-inserted.
memento.Rollback();
}
```

### Registering single properties/collections

You can also register single properties/collections, without the need to add attributes to your classes.

```csharp
var memento = Memento.Create()
.RegisterProperty(publisher, p => p.Name) //simple property
.RegisterProperty(publisher, p => p.ProfilePhoto.Description) //chain of properties
.RegisterProperty(() => ArticleFactory.LastReleaseDate) //static property
.RegisterCollection(articlesList);
```

## NuGet
To install MementoContainer, run the following command in the Package Manager Console

```
PM> Install-Package MementoContainer
```

## Depency Injection and Mocking
The IMemento interface is available so that you can easily mock it with tools like [Moq](https://code.google.com/p/moq/) in your unit tests and inject it as a depency using your favourite IoC container (e.g., [Castle Windsor](http://docs.castleproject.org/Windsor.MainPage.ashx) or [Ninject](http://www.ninject.org/)).

## Documentation
For more information and advanced usage, head on the [wiki].

[wiki]: https://github.com/dcastro/MementoContainer/wiki