Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dcastro/mementocontainer
https://github.com/dcastro/mementocontainer
Last synced: 26 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/dcastro/mementocontainer
- Owner: dcastro
- Created: 2013-08-14T12:19:12.000Z (about 11 years ago)
- Default Branch: dev
- Last Pushed: 2018-03-09T08:17:11.000Z (over 6 years ago)
- Last Synced: 2024-09-30T23:22:52.364Z (about 1 month ago)
- Language: C#
- Size: 415 KB
- Stars: 5
- Watchers: 2
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
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