Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using System.Linq;
12 : using System.Reflection;
13 : using cdmdotnet.Logging;
14 : using Cqrs.DataStores;
15 : using Cqrs.Mongo.DataStores.Indexes;
16 : using Cqrs.Mongo.Serialisers;
17 : using MongoDB.Driver;
18 : using MongoDB.Driver.Builders;
19 :
20 : namespace Cqrs.Mongo.Factories
21 : {
22 : /// <summary>
23 : /// A factory for obtaining <see cref="IDataStore{TData}"/> collections from Mongo
24 : /// </summary>
25 : public class MongoDataStoreFactory
26 1 : {
27 : private static IDictionary<Type, IList<object>> IndexTypesByEntityType { get; set; }
28 :
29 : /// <summary>
30 : /// Gets or sets the <see cref="ILogger"/>.
31 : /// </summary>
32 : protected ILogger Logger { get; private set; }
33 :
34 : /// <summary>
35 : /// Gets or sets the <see cref="IMongoDataStoreConnectionStringFactory"/>.
36 : /// </summary>
37 : protected IMongoDataStoreConnectionStringFactory MongoDataStoreConnectionStringFactory { get; private set; }
38 :
39 : /// <summary>
40 : /// Instantiate a new instance of <see cref="MongoDataStoreFactory"/>.
41 : /// </summary>
42 1 : public MongoDataStoreFactory(ILogger logger, IMongoDataStoreConnectionStringFactory mongoDataStoreConnectionStringFactory)
43 : {
44 : Logger = logger;
45 : MongoDataStoreConnectionStringFactory = mongoDataStoreConnectionStringFactory;
46 : }
47 :
48 : static MongoDataStoreFactory()
49 : {
50 : var typeSerializer = new TypeSerialiser();
51 : MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(typeof(Type), typeSerializer);
52 : MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(Type.GetType("System.RuntimeType"), typeSerializer);
53 :
54 : IndexTypesByEntityType = new Dictionary<Type, IList<object>>();
55 : foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
56 : {
57 : var mongoIndexTypes = assembly
58 : .GetTypes()
59 : .Where
60 : (
61 : type =>
62 : (
63 : // base is NOT an abstract index
64 : (
65 : type.BaseType != null &&
66 : type.BaseType.IsGenericType &&
67 : typeof(MongoIndex<>).IsAssignableFrom(type.BaseType.GetGenericTypeDefinition())
68 : )
69 : ||
70 : // base is an abstract index
71 : (
72 : type.BaseType != null &&
73 : type.BaseType.BaseType != null &&
74 : type.BaseType.BaseType.IsGenericType &&
75 : typeof(MongoIndex<>).IsAssignableFrom(type.BaseType.BaseType.GetGenericTypeDefinition())
76 : )
77 : ||
78 : // a deeper inheritance model
79 : (
80 : type.BaseType != null &&
81 : type.BaseType.BaseType != null &&
82 : type.BaseType.BaseType.BaseType != null &&
83 : type.BaseType.BaseType.BaseType.IsGenericType &&
84 : typeof(MongoIndex<>).IsAssignableFrom(type.BaseType.BaseType.BaseType.GetGenericTypeDefinition())
85 : )
86 : ||
87 : // an even deeper inheritance model
88 : (
89 : type.BaseType != null &&
90 : type.BaseType.BaseType != null &&
91 : type.BaseType.BaseType.BaseType != null &&
92 : type.BaseType.BaseType.BaseType.BaseType != null &&
93 : type.BaseType.BaseType.BaseType.BaseType.IsGenericType &&
94 : typeof(MongoIndex<>).IsAssignableFrom(type.BaseType.BaseType.BaseType.BaseType.GetGenericTypeDefinition())
95 : )
96 : )
97 : && !type.IsAbstract
98 : );
99 : foreach (Type mongoIndexType in mongoIndexTypes)
100 : {
101 : Type genericType = mongoIndexType;
102 : while (genericType != null && !genericType.IsGenericType)
103 : {
104 : genericType = genericType.BaseType;
105 : }
106 : genericType = genericType.GetGenericArguments().Single();
107 :
108 : IList<object> indexTypes;
109 : if (!IndexTypesByEntityType.TryGetValue(genericType, out indexTypes))
110 : IndexTypesByEntityType.Add(genericType, indexTypes = new List<object>());
111 : object mongoIndex = Activator.CreateInstance(mongoIndexType, true);
112 : indexTypes.Add(mongoIndex);
113 : }
114 : }
115 : }
116 :
117 : /// <summary>
118 : /// Get a <see cref="MongoCollection{TEntity}"/>
119 : /// </summary>
120 1 : protected virtual MongoCollection<TEntity> GetCollection<TEntity>()
121 : {
122 : var mongoClient = new MongoClient(MongoDataStoreConnectionStringFactory.GetMongoConnectionString());
123 : MongoServer mongoServer = mongoClient.GetServer();
124 : MongoDatabase mongoDatabase = mongoServer.GetDatabase(MongoDataStoreConnectionStringFactory.GetMongoDatabaseName());
125 :
126 : return mongoDatabase.GetCollection<TEntity>(typeof(TEntity).FullName);
127 : }
128 :
129 : /// <summary>
130 : /// Verify all required <see cref="IMongoIndexKeys"/> are defined and ready to go.
131 : /// </summary>
132 1 : protected virtual void VerifyIndexes<TEntity>(MongoCollection<TEntity> collection)
133 : {
134 : Type entityType = typeof (TEntity);
135 : if (IndexTypesByEntityType.ContainsKey(entityType))
136 : {
137 : foreach (object untypedIndexType in IndexTypesByEntityType[entityType])
138 : {
139 : var mongoIndex = (MongoIndex<TEntity>)untypedIndexType;
140 :
141 : var indexKeysBuilder = new IndexKeysBuilder();
142 : if (mongoIndex.IsAcending)
143 : indexKeysBuilder = indexKeysBuilder.Ascending(mongoIndex.Selectors.ToArray());
144 : else
145 : indexKeysBuilder = indexKeysBuilder.Descending(mongoIndex.Selectors.ToArray());
146 :
147 : collection.CreateIndex
148 : (
149 : indexKeysBuilder,
150 : IndexOptions
151 : .SetUnique(mongoIndex.IsUnique)
152 : .SetName(mongoIndex.Name)
153 : );
154 : }
155 : }
156 : }
157 : }
158 : }
|