private ORIDUpdater() { Type genericObjectType = typeof(T); foreach (PropertyInfo propertyInfo in genericObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (!propertyInfo.CanRead) { continue; // read only or write only properties can be ignored } string propertyName = propertyInfo.Name; var propertyType = propertyInfo.PropertyType; object[] oProperties = propertyInfo.GetCustomAttributes(typeof(OProperty), true); if (oProperties.Any()) { OProperty oProperty = oProperties.First() as OProperty; if (oProperty != null) { if (!oProperty.Deserializable) { continue; } propertyName = oProperty.Alias; } } if (propertyType == ORIDType && propertyInfo.CanWrite) { _fields.Add(new ORIDSimplePropertyUpdater <T>(propertyInfo)); } if (propertyType.IsArray && propertyType.GetElementType() == ORIDType) { _fields.Add(new ORIDArrayPropertyUpdater <T>(propertyInfo)); } if (propertyType.IsGenericType && propertyType.GetGenericArguments().First() == ORIDType) { switch (propertyType.Name) { case "HashSet`1": _fields.Add(new ORIDHashSetUpdater <T>(propertyInfo)); break; case "List`1": _fields.Add(new ORIDListPropertyUpdater <T>(propertyInfo)); break; default: throw new NotImplementedException("Generic ORID collection not handled."); } } } }
private TypeMapper() { Type genericObjectType = typeof(T); if (genericObjectType.Name.Equals("ODocument") || genericObjectType.Name.Equals("OVertex") || genericObjectType.Name.Equals("OEdge")) { _fields.Add(new AllFieldMapping <T>()); return; } foreach (PropertyInfo propertyInfo in genericObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (!propertyInfo.CanRead || !propertyInfo.CanWrite) { continue; // read only or write only properties can be ignored } string propertyName = propertyInfo.Name; // serialize orient specific fields into dedicated properties switch (propertyName) { case "ORID": _fields.Add(new ORIDFieldMapping <T>(propertyInfo)); continue; case "OVersion": _fields.Add(new OVersionFieldMapping <T>(propertyInfo)); continue; case "OClassId": _fields.Add(new OClassIdFieldMapping <T>(propertyInfo)); continue; case "OClassName": _fields.Add(new OClassNameFieldMapping <T>(propertyInfo)); continue; } object[] oProperties = propertyInfo.GetCustomAttributes(typeof(OProperty), true); if (oProperties.Any()) { OProperty oProperty = oProperties.First() as OProperty; if (oProperty != null) { if (!oProperty.Deserializable) { continue; } propertyName = oProperty.Alias; } } string fieldPath = propertyName; if (propertyInfo.PropertyType.IsArray) { _fields.Add(new ArrayNamedFieldMapping <T>(propertyInfo, fieldPath)); } else if (propertyInfo.PropertyType.IsGenericType) { _fields.Add(new ListNamedFieldMapping <T>(propertyInfo, fieldPath)); } // property is class except the string or ORID type since string and ORID values are parsed differently else if (propertyInfo.PropertyType.IsClass && (propertyInfo.PropertyType.Name != "String") && (propertyInfo.PropertyType.Name != "ORID")) { AddClassProperty(propertyInfo, fieldPath); } // property is basic type else { AddBasicProperty(propertyInfo, fieldPath); } } }
private static void InsertHelper <T>(ODatabase db, T model, OTransaction transaction, ICollection <object> exclude, ORID parent = null) where T : OBaseRecord, new() { // Avoid following loops into a stack overflow if (exclude.Contains(model)) { return; } exclude.Add(model); ODocument record = new ODocument(); record.OClassName = model.GetType().Name; PropertyInfo[] properties = model.GetType().GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.GetProperty); ICollection <PropertyInfo> linkableProperties = new List <PropertyInfo>(); foreach (PropertyInfo prop in properties) { if (reservedProperties.Contains(prop.Name)) { continue; } OProperty aliasProperty = prop.GetCustomAttributes(typeof(OProperty)) .Where(attr => ((OProperty)attr).Alias != null) .FirstOrDefault() as OProperty; string name = aliasProperty == null ? prop.Name : aliasProperty.Alias; // Record properties of model, but store properties linking to other // vertex classes for later if (typeof(OBaseRecord).IsAssignableFrom(prop.PropertyType)) { linkableProperties.Add(prop); } else { record[name] = prop.GetValue(model); } } transaction.Add(record); model.ORID = record.ORID; foreach (PropertyInfo prop in linkableProperties) { ORID outV, inV; OBaseRecord propValue = prop.GetValue(model) as OBaseRecord; if (!exclude.Select(ex => ex is OBaseRecord ? ((OBaseRecord)ex).ORID : ORID_DEFAULT).Contains(propValue.ORID)) { MethodInfo insertMethod = typeof(DatabaseExtensions) .GetMethod("InsertHelper", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(propValue.GetType()); insertMethod.Invoke(null, new object[] { db, propValue, transaction, exclude, model.ORID }); } outV = model.ORID; inV = propValue.ORID; OEdgeAttribute edgeType = prop.GetCustomAttributes(typeof(OEdgeAttribute)) .FirstOrDefault() as OEdgeAttribute; OProperty propertyAlias = prop.GetCustomAttributes(typeof(OProperty)) .Where(p => ((OProperty)p).Alias != null) .FirstOrDefault() as OProperty; string alias = propertyAlias == null ? prop.Name : propertyAlias.Alias; if (edgeType != null) { OEdge link = new OEdge(); link.OClassName = alias; link["out"] = outV; link["in"] = inV; if (edgeType.IsInV) { ORID tmp = link.OutV; link["out"] = link.InV; link["in"] = tmp; } // Do not create an edge if there is an edge already // connecting these vertices IEnumerable <Tuple <ORID, ORID> > excludedLinks = exclude .Select(ex => ex is OEdge ? new Tuple <ORID, ORID>(((OEdge)ex).OutV, ((OEdge)ex).InV) : new Tuple <ORID, ORID>(ORID_DEFAULT, ORID_DEFAULT)); if (excludedLinks.Contains( new Tuple <ORID, ORID>(link.OutV, link.InV))) { continue; } exclude.Add(link); transaction.Add(link); } } }