/// <summary> /// Copies a graph of entities of base type TFrom to a similar entity graph with base type TTo given the /// provided entity graph shape and type mapper. /// </summary> /// <typeparam name="TFrom">The base type of the source entity graph</typeparam> /// <typeparam name="TTo">The base type of the target entity graph</typeparam> /// <param name="shape">The entity graph shape defining the structure of the graph</param> /// <param name="fromEntity">The original entity</param> /// <param name="typeMapper">A class implementing ITypeMapper that maps subtypes of TFrom to sub types of TTo</param> /// <returns></returns> public static TTo CopyTo <TFrom, TTo>(this IEntityGraphShape shape, TFrom fromEntity, ITypeMapper typeMapper) where TFrom : class where TTo : class { if (fromEntity == null) { throw new ArgumentNullException("fromEntity"); } if (typeMapper == null) { throw new ArgumentNullException("typeMapper"); } return(CopyTo <TFrom, TTo>(shape, fromEntity, typeMapper, new List <TFrom>())); }
/// <summary> /// Creates a new entity graph for the given entity and shape and stores it in the /// cache, or returns the graph from the cache if it is already present there. /// </summary> /// <param name="entity"></param> /// <param name="shape"></param> /// <returns></returns> protected EntityGraph <TEntity> GetOrCreate(TEntity entity, IEntityGraphShape shape) { { int key = entity.GetHashCode() ^ shape.GetHashCode(); WeakReference reference = null; if (_entityGraphs.ContainsKey(key) == false) { reference = new WeakReference(null); _entityGraphs.Add(key, reference); } else { reference = _entityGraphs[key]; } if (reference.Target == null) { reference.Target = Create(entity, shape); } return(_entityGraphs[key].Target as EntityGraph <TEntity>); } }
/// <summary> /// Initializes a new instance of the EntityGraph class with given shape for given source entity. /// </summary> /// <param name="source"></param> /// <param name="graphShape"></param> public EntityGraph(TEntity source, IEntityGraphShape graphShape) { if (source == null) { throw new ArgumentNullException("source", "The cosntructor argument 'source' can't be null"); } if (graphShape == null) { throw new ArgumentNullException("graphShape", "The constructor argument 'graphShape' can't be null"); } this.Source = source; this.GraphShape = graphShape; var type = this.GetType(); var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; var constructors = type.GetMethods(flags).Where(m => m.IsDefined(typeof(InitializeAttribute), true)); foreach (var constructor in constructors) { constructor.Invoke(this, new object[] { }); } }
/// <summary> /// Creates a new entity graph for the given entity and shape and stores it in the /// cache, or returns the graph from the cache if it is already present there. /// </summary> /// <param name="entity"></param> /// <param name="shape"></param> /// <returns></returns> public static EntityGraph Get(Entity entity, IEntityGraphShape shape) { return(EntityGraphFactory._factory.GetOrCreate(entity, shape) as EntityGraph); }
protected override EntityGraph <Entity> Create(Entity entity, IEntityGraphShape shape) { return(new EntityGraph(entity, shape)); }
/// <summary> /// Extension method that clones the given entity and all associated entities in the entity graph defined by the given /// entity graph shape. The cloned entities are added/attached to the given domain context, which will give them /// the same EntityState as the original entities. /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="entity"></param> /// <param name="context"></param> /// <param name="shape"></param> /// <returns></returns> public static TEntity Clone <TEntity>(this TEntity entity, DomainContext context, IEntityGraphShape shape) where TEntity : Entity { return((TEntity)entity.EntityGraph(shape).Clone(context).Source); }
/// <summary> /// Extension method that clones the given entity and all associated entities in the entity graph defined by the given /// entity graph shape. /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="entity"></param> /// <param name="shape"></param> /// <returns></returns> public static TEntity Clone <TEntity>(this TEntity entity, IEntityGraphShape shape) where TEntity : Entity { return((TEntity)entity.EntityGraph(shape).Clone().Source); }
/// <summary> /// Extension method that returns an entity graph object as defined by the provided entity graph shape object. /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="entity"></param> /// <param name="shape"></param> /// <returns></returns> public static EntityGraph EntityGraph <TEntity>(this TEntity entity, IEntityGraphShape shape) where TEntity : Entity { return(EntityGraphFactory.Get(entity, shape)); }
protected abstract EntityGraph <TEntity> Create(TEntity entity, IEntityGraphShape shape);
/// <summary> /// Extension method that returns an entity graph object, defined by the provided entity graph shape /// </summary> /// <param name="Source"></param> /// <param name="shape"></param> public EntityGraph(Entity Source, IEntityGraphShape shape) : base(Source, shape) { }
private static TTo CopyTo <TFrom, TTo>(this IEntityGraphShape shape, TFrom fromEntity, ITypeMapper typeMapper, IList visited) where TFrom : class where TTo : class { var toEntity = CopyFromTo <TFrom, TTo>(fromEntity, typeMapper); Debug.Assert(visited.Contains(fromEntity) == false); visited.Add(fromEntity); // Determine if provided shape is defined for fromEntity or for toEntity. var outEdges = shape.OutEdges(fromEntity).ToList(); if (!outEdges.Any()) { outEdges = shape.OutEdges(toEntity).ToList(); } var fromType = fromEntity.GetType(); var toType = toEntity.GetType(); foreach (var edge in outEdges) { var fromPropInfo = fromType.GetProperty(edge.Name); var toPropInfo = toType.GetProperty(edge.Name); if (fromPropInfo == null || toPropInfo == null) { continue; } var fromPropvalue = fromPropInfo.GetValue(fromEntity, null); if (fromPropvalue == null) { continue; } if (typeof(IEnumerable).IsAssignableFrom(fromPropInfo.PropertyType)) { var fromChildren = (IEnumerable)fromPropvalue; var toList = (IEnumerable)toPropInfo.GetValue(toEntity, null); // If the IEnumerable is null, lets try to allocate one if (toList == null) { var constr = toPropInfo.PropertyType.GetConstructor(new Type[] {}); toList = (IEnumerable)constr.Invoke(new object[] {}); toPropInfo.SetValue(toEntity, toList, null); } var addMethod = toPropInfo.PropertyType.GetMethod("Add"); foreach (var fromChild in fromChildren) { if (visited.Contains(fromChild) == false) { var toChild = shape.CopyTo <TFrom, TTo>((TFrom)fromChild, typeMapper, visited); addMethod.Invoke(toList, new object[] { toChild }); } } } else { var fromChild = (TFrom)fromPropvalue; if (visited.Contains(fromChild) == false) { var toChild = shape.CopyTo <TFrom, TTo>(fromChild, typeMapper, visited); toPropInfo.SetValue(toEntity, toChild, null); } } } return(toEntity); }