Skip to content

Commit ff55fb5

Browse files
Introduced a new in-memory file based repository
1 parent 2495008 commit ff55fb5

File tree

4 files changed

+165
-3
lines changed

4 files changed

+165
-3
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
namespace DotNetToolkit.Repository.InMemory
2+
{
3+
using Properties;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Globalization;
7+
using System.IO;
8+
9+
/// <summary>
10+
/// Represents a file based repository for in-memory operations (for testing purposes).
11+
/// </summary>
12+
public abstract class InMemoryFileBasedRepositoryBase<TEntity, TKey> : InMemoryRepositoryBase<TEntity, TKey> where TEntity : class
13+
{
14+
#region Properties
15+
16+
/// <summary>
17+
/// Gets the file extension.
18+
/// </summary>
19+
protected abstract string FileExtension { get; }
20+
21+
#endregion
22+
23+
#region Constructors
24+
25+
/// <summary>
26+
/// Initializes a new instance of the <see cref="InMemoryFileBasedRepositoryBase{TEntity, TKey}"/> class.
27+
/// </summary>
28+
/// <param name="filePath">The file path.</param>
29+
protected InMemoryFileBasedRepositoryBase(string filePath)
30+
{
31+
OnInitialize(filePath);
32+
}
33+
34+
#endregion
35+
36+
#region Protected Methods
37+
38+
/// <summary>
39+
/// A protected overridable method for loading the entities from the specified stream reader.
40+
/// </summary>
41+
protected abstract IEnumerable<TEntity> OnLoaded(StreamReader reader);
42+
43+
/// <summary>
44+
/// A protected overridable method for saving the entities to the specified stream writer.
45+
/// </summary>
46+
protected abstract void OnSaved(StreamWriter writer, IEnumerable<TEntity> entities);
47+
48+
#endregion
49+
50+
#region Private Methods
51+
52+
private string ValidateFile(string filePath)
53+
{
54+
if (string.IsNullOrEmpty(filePath))
55+
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(filePath));
56+
57+
// Ensures we have a valid file
58+
var fileName = filePath;
59+
60+
if (Directory.Exists(filePath))
61+
{
62+
if (!fileName.EndsWith(@"\"))
63+
fileName += @"\";
64+
65+
fileName += $"{GetType().Name}{FileExtension}";
66+
}
67+
else
68+
{
69+
if (string.IsNullOrEmpty(Path.GetExtension(fileName)))
70+
fileName += FileExtension;
71+
72+
if (!Path.GetExtension(fileName).Equals(FileExtension))
73+
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.InvalidFileExtension, fileName, FileExtension));
74+
75+
if (fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0)
76+
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.InvalidFilePath, fileName));
77+
}
78+
79+
return fileName;
80+
}
81+
82+
private void OnInitialize(string filePath)
83+
{
84+
DatabaseName = ValidateFile(filePath);
85+
86+
// Creates the file if does not exist
87+
if (!File.Exists(DatabaseName))
88+
{
89+
File.Create(DatabaseName).Dispose();
90+
}
91+
// Otherwise, try to get the data from the file
92+
else
93+
{
94+
// Adds the data from the file into memory
95+
using (var stream = new FileStream(DatabaseName, FileMode.Open, FileAccess.Read))
96+
using (var reader = new StreamReader(stream))
97+
{
98+
var entities = OnLoaded(reader);
99+
100+
EnsureDeleted();
101+
102+
foreach (var entity in entities)
103+
{
104+
AddItem(entity);
105+
}
106+
107+
base.SaveChanges();
108+
}
109+
}
110+
}
111+
112+
#endregion
113+
114+
#region Overrides of InMemoryRepositoryBase<TEntity,TKey>
115+
116+
/// <summary>
117+
/// A protected overridable method for saving changes made in the current unit of work in the repository.
118+
/// </summary>
119+
protected override void SaveChanges()
120+
{
121+
using (var stream = new FileStream(DatabaseName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Delete))
122+
{
123+
// Saves the data into memory
124+
base.SaveChanges();
125+
126+
// Puts from memory into the file
127+
using (var writer = new StreamWriter(stream))
128+
{
129+
var entities = GetQuery();
130+
131+
OnSaved(writer, entities);
132+
}
133+
}
134+
}
135+
136+
#endregion
137+
}
138+
}

src/DotNetToolkit.Repository.InMemory/InMemoryRepositoryBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ protected InMemoryRepositoryBase(string databaseName = null)
5252
/// <summary>
5353
/// Ensures the in-memory store is completely deleted.
5454
/// </summary>
55-
public void EnsureDeleted()
55+
protected void EnsureDeleted()
5656
{
5757
_context.Clear();
5858
InMemoryCache<TEntity, TKey>.Instance.GetContext(DatabaseName).Clear();

src/DotNetToolkit.Repository.InMemory/Properties/Resources.Designer.cs

Lines changed: 20 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/DotNetToolkit.Repository.InMemory/Properties/Resources.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,10 @@
130130
<data name="EntityNotFoundInStore" xml:space="preserve">
131131
<value>Attempted to update or delete an entity that does not exist in the in-memory store.</value>
132132
</data>
133+
<data name="InvalidFileExtension" xml:space="preserve">
134+
<value>The specified '{0}' file has an invalid extension. Please consider using '{1}'.</value>
135+
</data>
136+
<data name="InvalidFilePath" xml:space="preserve">
137+
<value>The specified '{0}' file is not a valid path.</value>
138+
</data>
133139
</root>

0 commit comments

Comments
 (0)