Skip to content

Commit f0d9642

Browse files
committed
Initital checkin
0 parents  commit f0d9642

17 files changed

+978
-0
lines changed

.gitignore

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
#ignore thumbnails created by windows
3+
Thumbs.db
4+
#Ignore files build by Visual Studio
5+
*.obj
6+
*.exe
7+
*.pdb
8+
*.user
9+
*.aps
10+
*.pch
11+
*.vspscc
12+
*_i.c
13+
*_p.c
14+
*.ncb
15+
*.suo
16+
*.tlb
17+
*.tlh
18+
*.bak
19+
*.cache
20+
*.ilk
21+
*.log
22+
[Bb]in
23+
[Dd]ebug*/
24+
*.lib
25+
*.sbr
26+
obj/
27+
[Rr]elease*/
28+
_ReSharper*/
29+
[Tt]est[Rr]esult*

SimpleCQRS/AssemblyInfo.cs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
4+
// Information about this assembly is defined by the following attributes.
5+
// Change them to the values specific to your project.
6+
7+
[assembly: AssemblyTitle("SimpleCQRS")]
8+
[assembly: AssemblyDescription("")]
9+
[assembly: AssemblyConfiguration("")]
10+
[assembly: AssemblyCompany("")]
11+
[assembly: AssemblyProduct("")]
12+
[assembly: AssemblyCopyright("")]
13+
[assembly: AssemblyTrademark("")]
14+
[assembly: AssemblyCulture("")]
15+
16+
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
17+
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
18+
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
19+
20+
[assembly: AssemblyVersion("1.0.*")]
21+
22+
// The following attributes are used to specify the signing key for the assembly,
23+
// if desired. See the Mono documentation for more information about signing.
24+
25+
//[assembly: AssemblyDelaySign(false)]
26+
//[assembly: AssemblyKeyFile("")]
27+

SimpleCQRS/CommandHandlers.cs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
3+
namespace SimpleCQRS
4+
{
5+
public class LoggingHandler<T> :Handles<T> where T:Message
6+
{
7+
private readonly Handles<T> _next;
8+
9+
public LoggingHandler(Handles<T> next)
10+
{
11+
_next = next;
12+
}
13+
14+
public void Handle(T message)
15+
{
16+
Console.WriteLine("Logging Handler caught [" + typeof(T) + "]");
17+
_next.Handle(message);
18+
}
19+
}
20+
21+
public class CreateInventoryItemCommandHandler : Handles<CreateInventoryItem>
22+
{
23+
private readonly IRepository<InventoryItem> _repository;
24+
public CreateInventoryItemCommandHandler(IRepository<InventoryItem> repository)
25+
{
26+
_repository = repository;
27+
}
28+
public void Handle(CreateInventoryItem message)
29+
{
30+
var item = new InventoryItem(message.InventoryItemId, message.Name);
31+
_repository.Save(item, message.Version);
32+
}
33+
}
34+
35+
public class DeactivateInventoryItemCommandHandler : Handles<DeactivateInventoryItem>
36+
{
37+
private readonly IRepository<InventoryItem> _repository;
38+
public DeactivateInventoryItemCommandHandler(IRepository<InventoryItem> repository)
39+
{
40+
_repository = repository;
41+
}
42+
public void Handle(DeactivateInventoryItem message)
43+
{
44+
var item = _repository.GetById(message.InventoryItemId);
45+
item.Deactivate();
46+
_repository.Save(item, message.Version);
47+
}
48+
}
49+
50+
public class RemoveItemsFromInventoryCommandHandler : Handles<RemoveItemsFromInventory>
51+
{
52+
private readonly IRepository<InventoryItem> _repository;
53+
public RemoveItemsFromInventoryCommandHandler(IRepository<InventoryItem> repository)
54+
{
55+
_repository = repository;
56+
}
57+
public void Handle(RemoveItemsFromInventory message)
58+
{
59+
var item = _repository.GetById(message.InventoryItemId);
60+
item.Remove(message.Count);
61+
_repository.Save(item, message.Version);
62+
}
63+
}
64+
public class CheckInToInventoryCommandHandler : Handles<CheckInItemsToInventory>
65+
{
66+
private readonly IRepository<InventoryItem> _repository;
67+
public CheckInToInventoryCommandHandler(IRepository<InventoryItem> repository)
68+
{
69+
_repository = repository;
70+
}
71+
public void Handle(CheckInItemsToInventory message)
72+
{
73+
var item = _repository.GetById(message.InventoryItemId);
74+
item.CheckIn(message.Count);
75+
_repository.Save(item, message.Version);
76+
}
77+
}
78+
public class RenameInventoryItemCommandHandler : Handles<RenameInventoryItem>
79+
{
80+
private readonly IRepository<InventoryItem> _repository;
81+
public RenameInventoryItemCommandHandler(IRepository<InventoryItem> repository)
82+
{
83+
_repository = repository;
84+
}
85+
public void Handle(RenameInventoryItem message)
86+
{
87+
var item = _repository.GetById(message.InventoryItemId);
88+
item.ChangeName(message.NewName);
89+
_repository.Save(item, message.Version);
90+
}
91+
}
92+
93+
}

SimpleCQRS/Commands.cs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
namespace SimpleCQRS
3+
{
4+
public class Command : Message
5+
{
6+
public int Version;
7+
}
8+
9+
public class DeactivateInventoryItem : Command {
10+
public readonly Guid InventoryItemId;
11+
public DeactivateInventoryItem(Guid inventoryItemId) {
12+
InventoryItemId = inventoryItemId;
13+
}
14+
}
15+
16+
public class CreateInventoryItem : Command {
17+
public readonly Guid InventoryItemId;
18+
public readonly string Name;
19+
public CreateInventoryItem(Guid inventoryItemId, string name) {
20+
InventoryItemId = inventoryItemId;
21+
Name = name;
22+
}
23+
}
24+
25+
public class RenameInventoryItem : Command {
26+
public readonly Guid InventoryItemId;
27+
public readonly string NewName;
28+
public RenameInventoryItem(Guid inventoryItemId, string newName) {
29+
InventoryItemId = inventoryItemId;
30+
NewName = newName;
31+
}
32+
}
33+
34+
public class CheckInItemsToInventory : Command {
35+
public Guid InventoryItemId;
36+
public readonly int Count;
37+
public CheckInItemsToInventory(Guid inventoryItemId, int count) {
38+
InventoryItemId = inventoryItemId;
39+
Count = count;
40+
}
41+
}
42+
43+
public class RemoveItemsFromInventory : Command {
44+
public Guid InventoryItemId;
45+
public readonly int Count;
46+
47+
public RemoveItemsFromInventory(Guid inventoryItemId, int count) {
48+
InventoryItemId = inventoryItemId;
49+
Count = count;
50+
}
51+
}
52+
}

SimpleCQRS/Domain.cs

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace SimpleCQRS
5+
{
6+
public class InventoryItem : AggregateRoot
7+
{
8+
private bool _activated;
9+
private Guid _id;
10+
11+
private void Apply(InventoryItemCreated e)
12+
{
13+
_id = e.Id;
14+
_activated = true;
15+
}
16+
17+
private void Apply(InventoryItemDeactivated e)
18+
{
19+
_activated = false;
20+
}
21+
22+
public void ChangeName(string newName)
23+
{
24+
if (string.IsNullOrEmpty(newName)) throw new ArgumentException("newName");
25+
ApplyChange(new InventoryItemRenamed(_id, newName));
26+
}
27+
28+
public void Remove(int count)
29+
{
30+
if (count <= 0) throw new InvalidOperationException("cant remove negative count from inventory");
31+
ApplyChange(new ItemsRemovedFromInventory(_id, count));
32+
}
33+
34+
35+
public void CheckIn(int count)
36+
{
37+
if(count <= 0) throw new InvalidOperationException("must have a count greater than 0 to add to inventory");
38+
ApplyChange(new ItemsCheckedInToInventory(_id, count));
39+
}
40+
41+
public void Deactivate()
42+
{
43+
if(!_activated) throw new InvalidOperationException("already deactivated");
44+
ApplyChange(new InventoryItemDeactivated(_id));
45+
}
46+
47+
public override Guid Id
48+
{
49+
get { return _id; }
50+
}
51+
52+
public InventoryItem()
53+
{
54+
// used to create in repository ... many ways to avoid this, eg making private constructor
55+
}
56+
57+
public InventoryItem(Guid id, string name)
58+
{
59+
ApplyChange(new InventoryItemCreated(id, name));
60+
}
61+
}
62+
63+
public abstract class AggregateRoot
64+
{
65+
private readonly List<Event> _changes = new List<Event>();
66+
67+
public abstract Guid Id { get; }
68+
69+
public IEnumerable<Event> GetUncommittedChanges()
70+
{
71+
return _changes;
72+
}
73+
74+
public void MarkChangesAsCommitted()
75+
{
76+
_changes.Clear();
77+
}
78+
79+
public void LoadsFromHistory(IEnumerable<Event> history)
80+
{
81+
foreach (var e in history) ApplyChange(e, false);
82+
}
83+
84+
protected void ApplyChange(Event @event)
85+
{
86+
ApplyChange(@event, true);
87+
}
88+
89+
private void ApplyChange(Event @event, bool isNew)
90+
{
91+
this.AsDynamic().Apply(@event);
92+
if(isNew) _changes.Add(@event);
93+
}
94+
}
95+
96+
public interface IRepository<T> where T : AggregateRoot, new()
97+
{
98+
void Save(AggregateRoot aggregate, int expectedVersion);
99+
T GetById(Guid id);
100+
}
101+
102+
public class Repository<T> : IRepository<T> where T: AggregateRoot, new() //shortcut you can do as you see fit with new()
103+
{
104+
private readonly IEventStore _storage;
105+
106+
public Repository(IEventStore storage)
107+
{
108+
_storage = storage;
109+
}
110+
111+
public void Save(AggregateRoot aggregate, int expectedVersion)
112+
{
113+
_storage.SaveEvents(aggregate.Id, aggregate.GetUncommittedChanges(), expectedVersion);
114+
}
115+
116+
public T GetById(Guid id)
117+
{
118+
var obj = new T();
119+
obj.LoadsFromHistory(_storage.GetEventsForAggregate(id));
120+
return obj;
121+
}
122+
}
123+
124+
}
125+

0 commit comments

Comments
 (0)