Skip to content

Commit

Permalink
First MongoDB boostrapping version.
Browse files Browse the repository at this point in the history
  • Loading branch information
nscheibe committed Nov 28, 2019
1 parent 856db24 commit 6fdd303
Show file tree
Hide file tree
Showing 12 changed files with 482 additions and 6 deletions.
25 changes: 25 additions & 0 deletions src/Context/Context.csproj
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>MongoDB.Extensions.Context</AssemblyName>
<RootNamespace>MongoDB.Extensions.Context</RootNamespace>
<PackageId>MongoDB.Extensions.Context</PackageId>
<IsPackable>false</IsPackable>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.9.3" />
</ItemGroup>

</Project>
21 changes: 21 additions & 0 deletions src/Context/IMongoCollectionBuilder.cs
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;

namespace MongoDB.Bootstrapper
{
public interface IMongoCollectionBuilder<TDocument>
{
IMongoCollectionBuilder<TDocument> WithCollectionName(string collectionName);

IMongoCollectionBuilder<TDocument> AddBsonClassMap<TMapDocument>(
Action<BsonClassMap<TMapDocument>> bsonClassMapAction) where TMapDocument : class;

IMongoCollectionBuilder<TDocument> WithMongoCollectionSettings(
Action<MongoCollectionSettings> collectionSettings);

IMongoCollectionBuilder<TDocument> WithMongoCollectionConfiguration(
Action<IMongoCollection<TDocument>> collectionConfiguration);
}
}
7 changes: 7 additions & 0 deletions src/Context/IMongoCollectionConfiguration.cs
@@ -0,0 +1,7 @@
namespace MongoDB.Bootstrapper
{
public interface IMongoCollectionConfiguration<TDocument> where TDocument : class
{
void Configure(IMongoCollectionBuilder<TDocument> mongoCollectionBuilder);
}
}
25 changes: 25 additions & 0 deletions src/Context/IMongoDatabaseBuilder.cs
@@ -0,0 +1,25 @@
using System;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Driver;

namespace MongoDB.Bootstrapper
{
public interface IMongoDatabaseBuilder
{
IMongoDatabaseBuilder Initialize(Action initialization);

IMongoDatabaseBuilder RegisterSerializer<T>(IBsonSerializer<T> serializer);

IMongoDatabaseBuilder RegisterConventionPack(
string name, IConventionPack conventions, Func<Type, bool> filter);

IMongoDatabaseBuilder RegisterCamelCaseConventionPack();

IMongoDatabaseBuilder ConfigureCollection<TDocument>(
IMongoCollectionConfiguration<TDocument> configuration) where TDocument : class;

IMongoDatabaseBuilder ConfigureConnection(
Action<MongoClientSettings> mongoClientSettingsAction);
}
}
13 changes: 13 additions & 0 deletions src/Context/IMongoDbContext.cs
@@ -0,0 +1,13 @@
using MongoDB.Driver;

namespace MongoDB.Bootstrapper
{
public interface IMongoDbContext
{
MongoOptions MongoOptions { get; }
IMongoClient Client { get; }
IMongoDatabase Database { get; }

IMongoCollection<TDocument> CreateCollection<TDocument>() where TDocument : class;
}
}
82 changes: 82 additions & 0 deletions src/Context/Internal/MongoCollectionBuilder.cs
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;

namespace MongoDB.Bootstrapper
{
internal class MongoCollectionBuilder<TDocument> : IMongoCollectionBuilder<TDocument>
{
private string _collectionName;
private readonly IMongoDatabase _mongoDatabase;
private readonly List<Action<MongoCollectionSettings>> _collectionSettingsActions;
private readonly List<Action<IMongoCollection<TDocument>>> _collectionConfigurations;

public MongoCollectionBuilder(IMongoDatabase mongoDatabase)
{
_collectionName = typeof(TDocument).Name;
_collectionConfigurations = new List<Action<IMongoCollection<TDocument>>>();
_collectionSettingsActions = new List<Action<MongoCollectionSettings>>();

_mongoDatabase = mongoDatabase ??
throw new ArgumentNullException(nameof(mongoDatabase));
}

public IMongoCollectionBuilder<TDocument> WithCollectionName(string collectionName)
{
if (string.IsNullOrEmpty(collectionName))
throw new ArgumentException("Mongo collection name must not be null or empty.");

_collectionName = collectionName;

return this;
}

public IMongoCollectionBuilder<TDocument> AddBsonClassMap<TMapDocument>(
Action<BsonClassMap<TMapDocument>> bsonClassMapAction) where TMapDocument : class
{
if (!BsonClassMap.IsClassMapRegistered(typeof(TMapDocument)))
{
BsonClassMap.RegisterClassMap(bsonClassMapAction);
}

return this;
}

public IMongoCollectionBuilder<TDocument> WithMongoCollectionSettings(
Action<MongoCollectionSettings> collectionSettings)
{
_collectionSettingsActions.Add(collectionSettings);

return this;
}

public IMongoCollectionBuilder<TDocument> WithMongoCollectionConfiguration(
Action<IMongoCollection<TDocument>> collectionConfiguration)
{
_collectionConfigurations.Add(collectionConfiguration);

return this;
}

internal IMongoCollection<TDocument> Build()
{
MongoCollectionSettings mongoCollectionSettings = null;

if (_collectionSettingsActions.Count != 0)
{
mongoCollectionSettings = new MongoCollectionSettings();
_collectionSettingsActions
.ForEach(configure => configure(mongoCollectionSettings));
}

IMongoCollection<TDocument> mongoCollection = _mongoDatabase
.GetCollection<TDocument>(_collectionName, mongoCollectionSettings);

_collectionConfigurations
.ForEach(configuration => configuration(mongoCollection));

return mongoCollection;
}
}
}
137 changes: 137 additions & 0 deletions src/Context/Internal/MongoDatabaseBuilder.cs
@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Driver;

namespace MongoDB.Bootstrapper
{
internal class MongoDatabaseBuilder : IMongoDatabaseBuilder
{
private readonly MongoOptions _mongoOptions;
private readonly List<Action> _initializationActions;
private readonly List<Action<MongoClientSettings>> _mongoClientSettingsActions;
private readonly List<Action<IMongoDatabase, Dictionary<Type, object>>> _builderActions;

public MongoDatabaseBuilder(MongoOptions mongoOptions)
{
_mongoOptions = mongoOptions;
_initializationActions = new List<Action>();
_mongoClientSettingsActions = new List<Action<MongoClientSettings>>();
_builderActions = new List<Action<IMongoDatabase, Dictionary<Type, object>>>();
}

public IMongoDatabaseBuilder Initialize(Action initialization)
{
_initializationActions.Add(initialization);

return this;
}

public IMongoDatabaseBuilder ConfigureConnection(
Action<MongoClientSettings> mongoClientSettingsAction)
{
_mongoClientSettingsActions.Add(mongoClientSettingsAction);

return this;
}

public IMongoDatabaseBuilder ConfigureCollection<TDocument>(
IMongoCollectionConfiguration<TDocument> configuration) where TDocument : class
{
Action<IMongoDatabase, Dictionary<Type, object>> buildAction = (mongoDb, mongoCollectionBuilders) =>
{
if (mongoCollectionBuilders.ContainsKey(typeof(TDocument)))
{
throw new Exception($"The mongo collection configuration for " +
$"document type '{typeof(TDocument)}' already exists.");
}
var collectionBuilder = new MongoCollectionBuilder<TDocument>(mongoDb);
configuration.Configure(collectionBuilder);
collectionBuilder.Build();
mongoCollectionBuilders.Add(typeof(TDocument), collectionBuilder);
};

_builderActions.Add(buildAction);

return this;
}

public IMongoDatabaseBuilder RegisterCamelCaseConventionPack()
{
RegisterConventionPack("camelCase", new ConventionPack
{
new EnumRepresentationConvention(BsonType.String),
new CamelCaseElementNameConvention()
}, t => true);

return this;
}

public IMongoDatabaseBuilder RegisterConventionPack(
string name, IConventionPack conventions, Func<Type, bool> filter)
{
Action initAction = () =>
{
// TODO Create a dictionary with the name and type and if the name already exists, then check if the save conventions of the conventionpacks are registered, if not than throw an exception.
// Register when name not exist
// Register when name exists and the conventions types are the same
// Throw exception if the name exist, but conventions are different.
//ConventionRegistry.Remove(name);
IConventionPack dd = ConventionRegistry.Lookup(typeof(string));
IEnumerable<IConvention> daa = dd.Conventions;
ConventionRegistry.Register(name, conventions, filter);
IConventionPack ddaaa = ConventionRegistry.Lookup(typeof(string));
IEnumerable<IConvention> daaadfa = ddaaa.Conventions;
};

_initializationActions.Add(initAction);

return this;
}

public IMongoDatabaseBuilder RegisterSerializer<T>(IBsonSerializer<T> serializer)
{
Action initAction = () =>
{
// TODO Create dictionary with the type and serializer type and if the type does already exist, then check if the serializer type is the same, if not throw exception.
BsonSerializer.RegisterSerializer<T>(serializer);
};

_initializationActions.Add(initAction);

return this;
}

internal MongoDbContextData Build()
{
_initializationActions.ForEach(init => init());

var mongoClientSettings = MongoClientSettings
.FromConnectionString(_mongoOptions.ConnectionString);

_mongoClientSettingsActions.ForEach(
settings => settings(mongoClientSettings));

var mongoClient = new MongoClient(mongoClientSettings);
IMongoDatabase mongoDatabase = mongoClient
.GetDatabase(_mongoOptions.DatabaseName);

var mongoCollectionBuilders = new Dictionary<Type, object>();

_builderActions.ForEach(
config => config(mongoDatabase, mongoCollectionBuilders));

return new MongoDbContextData(
mongoClient, mongoDatabase, mongoCollectionBuilders);
}
}
}
51 changes: 51 additions & 0 deletions src/Context/Internal/MongoDbContextData.cs
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using MongoDB.Driver;

namespace MongoDB.Bootstrapper
{
internal class MongoDbContextData
{
private readonly Dictionary<Type, object> _mongoCollectionBuilders;

public MongoDbContextData(
IMongoClient mongoClient,
IMongoDatabase mongoDatabase,
Dictionary<Type, object> mongoCollectionBuilders)
{
//TODO check for nulls
MongoClient = mongoClient;
MongoDatabase = mongoDatabase;
_mongoCollectionBuilders = mongoCollectionBuilders;
}

public IMongoClient MongoClient { get; }
public IMongoDatabase MongoDatabase { get; }

internal IMongoCollection<TDocument> CreateCollection<TDocument>() where TDocument : class
{
MongoCollectionBuilder<TDocument> collectionBuilder =
TryGetCollectionBuilder<TDocument>();

if (collectionBuilder == null)
{
collectionBuilder = new MongoCollectionBuilder<TDocument>(MongoDatabase);
}

return collectionBuilder.Build();
}

private MongoCollectionBuilder<TDocument> TryGetCollectionBuilder<TDocument>() where TDocument : class
{
MongoCollectionBuilder<TDocument> collectionBuilder = null;

if (_mongoCollectionBuilders.ContainsKey(typeof(TDocument)))
{
collectionBuilder = (MongoCollectionBuilder<TDocument>)
_mongoCollectionBuilders[typeof(TDocument)];
}

return collectionBuilder;
}
}
}

0 comments on commit 6fdd303

Please sign in to comment.