sharp-oodb/OODB.cs

187 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using oodb.descriptor;
using oodb.mapping;
using oodb.persistence;
using System.IO;
using System.Linq;
using System.Xml;
using System.CodeDom;
using System.ComponentModel;
using System.Reflection;
using oodb.mapping.collections;
namespace oodb
{
public class OODB
{
public PersistenceCache PersistenceCache { get; }
public StorageAdapter StorageAdapter { get; }
internal Dictionary<Type, Descriptor> descriptors = new Dictionary<Type, Descriptor>();
internal Dictionary<Type, FlatTypeMapping> flatTypeMappings = new Dictionary<Type, FlatTypeMapping>();
public OODB(String storagePath)
:this(new DirectoryInfo(storagePath))
{
}
public OODB(DirectoryInfo storageDirectory)
{
PersistenceCache = new PersistenceCache(this);
StorageAdapter = new StorageAdapter(this,storageDirectory);
PopulateFlatMappings();
AppDomain.CurrentDomain.ProcessExit += (sender, e) => this.Close();
}
public void Close()
{
StorageAdapter.Close();
}
public void Prepare()
{
foreach (Descriptor descriptor in descriptors.Values)
{
descriptor.Initialize();
}
}
public OODB Add<T>() where T : Persistent => Add(typeof(T));
public OODB Add(Type type)
{
GetDescriptor(type);
return this;
}
public void Save(IEnumerable<Persistent> persistents)
{
foreach (Persistent persistent in persistents)
Save(persistent);
}
public void Save(Persistent o)
{
PersistenceCache.Touch(o);
StorageAdapter.Save(o);
}
public void Ensure(Persistent o)
{
if (!StorageAdapter.Knows(o.GetType(), o.PersistenceID))
Save(o);
}
public T Load<T>(Guid persistenceID) where T: Persistent
{
return (T)Load(typeof(T), persistenceID);
}
public Persistent Load(Type type,Guid persistenceID)
{
if (persistenceID.Equals(Guid.Empty))
return null;
try {
return PersistenceCache.Get(type, persistenceID);
} catch (KeyNotFoundException)
{
Type realType = StorageAdapter.GetDiscriminator(type, persistenceID);
Persistent persistent = Activator.CreateInstance(type,true) as Persistent;
persistent.PersistenceID = persistenceID;
PersistenceCache.Touch(persistent);
GetDescriptor(realType).Attach(persistent);
StorageAdapter.Restore(persistent);
return persistent;
}
}
public IEnumerable<T> List<T>() where T:Persistent => List(typeof(T)).Select((x) => (T)x);
public IEnumerable<Persistent> List(Type type)
{
return ListIdentities(type).Select((x) => Load(x.Value, x.Key));
}
private IEnumerable<KeyValuePair<Guid,Type>> ListIdentities(Type type)
{
return StorageAdapter.List(GetDescriptor(type));
}
public Type LookupType(string fullName)
{
foreach (Type t in descriptors.Keys)
if (t.FullName.Equals(fullName))
return t;
throw new KeyNotFoundException(fullName);
}
public Descriptor GetDescriptor(Type type)
{
if (!descriptors.ContainsKey(type))
{
descriptors[type] = new Descriptor(this, type);
}
return descriptors[type];
}
public Descriptor GetDescriptor<T>() => GetDescriptor(typeof(T));
public FlatTypeMapping GetFlatTypeMapping(Type type)
{
if (!flatTypeMappings.ContainsKey(type))
{
if (type.IsArray)
{
flatTypeMappings[type] = new ArrayMapping(this, type);
}
else if (type.IsSubclassOf(typeof(Persistent)))
{
Add(type);
}
else if (type.IsGenericType && ((type.GetGenericTypeDefinition() == typeof(List<>)) || (type.GetGenericTypeDefinition() == typeof(IList<>))))
{
FlatTypeMapping elementMapping = GetFlatTypeMapping(type.GetGenericArguments()[0]);
flatTypeMappings[type] = new ListMapping(this, type);
} else {
throw new KeyNotFoundException();
}
}
return flatTypeMappings[type];
}
public ExtendedFieldHandling CreateExtendedFieldHandling(FieldInfo fieldInfo)
{
if (fieldInfo.FieldType.IsGenericType){
Type genericTypeDefinition = fieldInfo.FieldType.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(ISet<>))
{
return new ISetExtendedHandling(this, fieldInfo);
}
}
throw new NotSupportedException();
}
private void PopulateFlatMappings()
{
flatTypeMappings[typeof(string)] = new StringMapping(this);
flatTypeMappings[typeof(int)] = new IntegerMapping(this);
flatTypeMappings[typeof(short)] = new IntegerMapping(this);
flatTypeMappings[typeof(byte)] = new IntegerMapping(this);
flatTypeMappings[typeof(float)] = new DoubleMapping(this);
flatTypeMappings[typeof(double)] = new DoubleMapping(this);
}
}
}