Example #1
0
        /// <summary>
        /// Tries to get the value of a property and corresponding BindingPropertyInfo or ClientPropertyAnnotation if the property exists
        /// </summary>
        /// <param name="source">Source object whose property needs to be read</param>
        /// <param name="sourceProperty">Name of the source object property</param>
        /// <param name="model">The client model.</param>
        /// <param name="bindingPropertyInfo">BindingPropertyInfo corresponding to <paramref name="sourceProperty"/></param>
        /// <param name="clientProperty">Instance of ClientProperty corresponding to <paramref name="sourceProperty"/></param>
        /// <param name="propertyValue">Value of the property</param>
        /// <returns>true if the property exists and the value was read; otherwise false.</returns>
        internal static bool TryGetPropertyValue(object source, string sourceProperty, ClientEdmModel model, out BindingPropertyInfo bindingPropertyInfo, out ClientPropertyAnnotation clientProperty, out object propertyValue)
        {
            Type sourceType = source.GetType();

            bindingPropertyInfo = BindingEntityInfo.GetObservableProperties(sourceType, model)
                                  .SingleOrDefault(x => x.PropertyInfo.PropertyName == sourceProperty);

            bool propertyFound = bindingPropertyInfo != null;

            // bindingPropertyInfo is null for primitive properties.
            if (!propertyFound)
            {
                clientProperty = BindingEntityInfo.GetClientType(sourceType, model)
                                 .GetProperty(sourceProperty, true);

                propertyFound = clientProperty != null;
                if (!propertyFound)
                {
                    propertyValue = null;
                }
                else
                {
                    propertyValue = clientProperty.GetValue(source);
                }
            }
            else
            {
                clientProperty = null;
                propertyValue  = bindingPropertyInfo.PropertyInfo.GetValue(source);
            }

            return(propertyFound);
        }
Example #2
0
        private object GetCollectionInstance(ClientPropertyAnnotation property, out bool instanceCreated)
        {
            instanceCreated = false;
            object obj2 = property.GetValue(this.entity);

            if (obj2 != null)
            {
                return(obj2);
            }
            instanceCreated = true;
            Type propertyType = property.PropertyType;

            if (BindingEntityInfo.IsDataServiceCollection(propertyType, base.RequestInfo.MaxProtocolVersion))
            {
                object[] args = new object[2];
                args[1] = TrackingMode.None;
                return(Activator.CreateInstance(WebUtil.GetDataServiceCollectionOfT(new Type[] { property.EntityCollectionItemType }), args));
            }
            Type c = typeof(List <>).MakeGenericType(new Type[] { property.EntityCollectionItemType });

            if (!propertyType.IsAssignableFrom(c))
            {
                c = propertyType;
            }
            return(Activator.CreateInstance(c));
        }
        /// <summary>
        /// Builds an edm property value from the given annotation.
        /// </summary>
        /// <param name="propertyAnnotation">The property annotation.</param>
        /// <returns>The property value</returns>
        private IEdmPropertyValue BuildEdmPropertyValue(ClientPropertyAnnotation propertyAnnotation)
        {
            var propertyValue = propertyAnnotation.GetValue(this.structuredValue);
            var edmValue      = this.ConvertToEdmValue(propertyValue, propertyAnnotation.EdmProperty.Type);

            return(new EdmPropertyValue(propertyAnnotation.EdmProperty.Name, edmValue));
        }
Example #4
0
        internal static object ProjectionInitializeEntity(ODataEntityMaterializer materializer, MaterializerEntry entry, Type expectedType, Type resultType, string[] properties, Func <object, object, Type, object>[] propertyValues)
        {
            if (entry.Entry == null)
            {
                throw new NullReferenceException(System.Data.Services.Client.Strings.AtomMaterializer_EntryToInitializeIsNull(resultType.FullName));
            }
            if (!entry.EntityHasBeenResolved)
            {
                ProjectionEnsureEntryAvailableOfType(materializer, entry, resultType);
            }
            else if (!resultType.IsAssignableFrom(entry.ActualType.ElementType))
            {
                throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomMaterializer_ProjectEntityTypeMismatch(resultType.FullName, entry.ActualType.ElementType.FullName, entry.Entry.Id));
            }
            object resolvedObject = entry.ResolvedObject;

            for (int i = 0; i < properties.Length; i++)
            {
                StreamDescriptor         descriptor;
                string                   propertyName = properties[i];
                ClientPropertyAnnotation annotation   = entry.ActualType.GetProperty(propertyName, materializer.ResponseInfo.IgnoreMissingProperties);
                object                   target       = propertyValues[i](materializer, entry.Entry, expectedType);
                ODataProperty            property     = (from p in entry.Entry.Properties
                                                         where p.Name == propertyName
                                                         select p).FirstOrDefault <ODataProperty>();
                if ((((((property == null) && (entry.NavigationLinks != null)) ? (from l in entry.NavigationLinks
                                                                                  where l.Name == propertyName
                                                                                  select l).FirstOrDefault <ODataNavigationLink>() : null) != null) || (property != null)) || entry.EntityDescriptor.TryGetNamedStreamInfo(propertyName, out descriptor))
                {
                    if (entry.ShouldUpdateFromPayload && (annotation.EdmProperty.Type.TypeKind() == EdmTypeKind.Entity))
                    {
                        materializer.Log.SetLink(entry, annotation.PropertyName, target);
                    }
                    if (entry.ShouldUpdateFromPayload)
                    {
                        if (!annotation.IsEntityCollection)
                        {
                            if (!annotation.IsPrimitiveOrComplexCollection)
                            {
                                annotation.SetValue(resolvedObject, target, annotation.PropertyName, false);
                            }
                        }
                        else
                        {
                            IEnumerable list = (IEnumerable)target;
                            DataServiceQueryContinuation continuation = materializer.nextLinkTable[list];
                            Uri            nextLink = (continuation == null) ? null : continuation.NextLinkUri;
                            ProjectionPlan plan     = (continuation == null) ? null : continuation.Plan;
                            materializer.MergeLists(entry, annotation, list, nextLink, plan);
                        }
                    }
                    else if (annotation.IsEntityCollection)
                    {
                        materializer.FoundNextLinkForUnmodifiedCollection(annotation.GetValue(entry.ResolvedObject) as IEnumerable);
                    }
                }
            }
            return(resolvedObject);
        }
Example #5
0
        /// <summary>
        /// Gets or creates a collection property on the specified <paramref name="instance"/>.
        /// </summary>
        /// <param name="instance">Instance on which to get/create the collection.</param>
        /// <param name="property">Collection property on the <paramref name="instance"/>.</param>
        /// <param name="forLoadProperty">Is this collection being created for LoadProperty scenario.</param>
        /// <returns>
        /// The collection corresponding to the specified <paramref name="property"/>;
        /// never null.
        /// </returns>
        private object GetOrCreateCollectionProperty(object instance, ClientPropertyAnnotation property, bool forLoadProperty)
        {
            Debug.Assert(instance != null, "instance != null");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(property.IsResourceSet, "property.IsEntityCollection has to be true - otherwise property isn't a collection");

            // NOTE: in V1, we would have instantiated nested objects before setting them.
            object result;

            result = property.GetValue(instance);

            if (result == null)
            {
                Type collectionType = property.PropertyType;

                // For backward compatibility we need to have different strategy of collection creation b/w
                // LoadProperty scenario versus regular collection creation scenario.
                if (forLoadProperty)
                {
                    if (BindingEntityInfo.IsDataServiceCollection(collectionType, this.MaterializerContext.Model))
                    {
                        Debug.Assert(WebUtil.GetDataServiceCollectionOfT(property.EntityCollectionItemType) != null, "DataServiceCollection<> must be available here.");

                        // new DataServiceCollection<property.EntityCollectionItemType>(null, TrackingMode.None)
                        result = Activator.CreateInstance(
                            WebUtil.GetDataServiceCollectionOfT(property.EntityCollectionItemType),
                            null,
                            TrackingMode.None);
                    }
                    else
                    {
                        // Try List<> first because that's what we did in V1/V2, but use the actual property type if it doesn't support List<>
                        Type listCollectionType = typeof(List <>).MakeGenericType(property.EntityCollectionItemType);
                        if (collectionType.IsAssignableFrom(listCollectionType))
                        {
                            collectionType = listCollectionType;
                        }

                        result = Activator.CreateInstance(collectionType);
                    }
                }
                else
                {
                    if (DSClient.PlatformHelper.IsInterface(collectionType))
                    {
                        collectionType = typeof(System.Collections.ObjectModel.Collection <>).MakeGenericType(property.EntityCollectionItemType);
                    }

                    result = this.CreateNewInstance(property.EdmProperty.Type, collectionType);
                }

                // Update the property value on the instance.
                property.SetValue(instance, result, property.PropertyName, false /* add */);
            }

            Debug.Assert(result != null, "result != null -- otherwise GetOrCreateCollectionProperty didn't fall back to creation");
            return(result);
        }
Example #6
0
        private void ApplyItemsToCollection(MaterializerEntry entry, ClientPropertyAnnotation property, IEnumerable items, Uri nextLink, ProjectionPlan continuationPlan)
        {
            Func <LinkDescriptor, bool> predicate     = null;
            object               instance             = entry.ShouldUpdateFromPayload ? GetOrCreateCollectionProperty(entry.ResolvedObject, property, null) : null;
            ClientEdmModel       model                = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);
            ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(property.EntityCollectionItemType));

            foreach (object obj3 in items)
            {
                if (!clientTypeAnnotation.ElementType.IsAssignableFrom(obj3.GetType()))
                {
                    throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomMaterializer_EntryIntoCollectionMismatch(obj3.GetType().FullName, clientTypeAnnotation.ElementType.FullName));
                }
                if (entry.ShouldUpdateFromPayload)
                {
                    property.SetValue(instance, obj3, property.PropertyName, true);
                    this.log.AddedLink(entry, property.PropertyName, obj3);
                }
            }
            if (entry.ShouldUpdateFromPayload)
            {
                this.FoundNextLinkForCollection(instance as IEnumerable, nextLink, continuationPlan);
            }
            else
            {
                this.FoundNextLinkForUnmodifiedCollection(property.GetValue(entry.ResolvedObject) as IEnumerable);
            }
            if ((this.mergeOption == MergeOption.OverwriteChanges) || (this.mergeOption == MergeOption.PreserveChanges))
            {
                if (predicate == null)
                {
                    predicate = delegate(LinkDescriptor x) {
                        if (MergeOption.OverwriteChanges != this.mergeOption)
                        {
                            return(EntityStates.Added != x.State);
                        }
                        return(true);
                    };
                }
                foreach (object obj4 in (from x in base.ResponseInfo.EntityTracker.GetLinks(entry.ResolvedObject, property.PropertyName).Where <LinkDescriptor>(predicate) select x.Target).Except <object>(EnumerateAsElementType <object>(items)))
                {
                    if (instance != null)
                    {
                        property.RemoveValue(instance, obj4);
                    }
                    this.log.RemovedLink(entry, property.PropertyName, obj4);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Populates the collection property on the entry's resolved object with the given items enumerator.
        /// </summary>
        /// <param name="entry">Entry with collection to be modified.</param>
        /// <param name="property">Collection property on the entry.</param>
        /// <param name="items">Values to apply onto the collection.</param>
        /// <param name="nextLink">Next link for collection continuation.</param>
        /// <param name="continuationPlan">Projection plan for collection continuation.</param>
        /// <returns>Collection instance that was populated.</returns>
        private object PopulateCollectionProperty(
            MaterializerEntry entry,
            ClientPropertyAnnotation property,
            IEnumerable <object> items,
            Uri nextLink,
            ProjectionPlan continuationPlan)
        {
            Debug.Assert(entry.Entry != null || entry.ForLoadProperty, "ODataResource should be non-null except for LoadProperty");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(items != null, "items != null");

            object collection = null;

            ClientEdmModel       edmModel       = this.MaterializerContext.Model;
            ClientTypeAnnotation collectionType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(property.ResourceSetItemType));

            if (entry.ShouldUpdateFromPayload)
            {
                collection = this.GetOrCreateCollectionProperty(entry.ResolvedObject, property, entry.ForLoadProperty);

                foreach (object item in items)
                {
                    // Validate that item can be inserted into collection.
                    ValidateCollectionElementTypeIsItemType(item.GetType(), collectionType.ElementType);

                    property.SetValue(collection, item, property.PropertyName, true /* allowAdd? */);

                    this.EntityTrackingAdapter.MaterializationLog.AddedLink(entry, property.PropertyName, item);
                }

                this.FoundNextLinkForCollection(collection as IEnumerable, nextLink, continuationPlan);
            }
            else
            {
                Debug.Assert(!entry.ForLoadProperty, "LoadProperty should always have ShouldUpdateForPayload set to true.");

                foreach (object item in items)
                {
                    // Validate that item can be inserted into collection.
                    ValidateCollectionElementTypeIsItemType(item.GetType(), collectionType.ElementType);
                }

                this.FoundNextLinkForUnmodifiedCollection(property.GetValue(entry.ResolvedObject) as IEnumerable);
            }

            return(collection);
        }
Example #8
0
        private static object GetOrCreateCollectionProperty(object instance, ClientPropertyAnnotation property, Type collectionType)
        {
            object obj2 = property.GetValue(instance);

            if (obj2 == null)
            {
                if (collectionType == null)
                {
                    collectionType = property.PropertyType;
                    if (collectionType.IsInterfaceEx())
                    {
                        collectionType = typeof(Collection <>).MakeGenericType(new Type[] { property.EntityCollectionItemType });
                    }
                }
                obj2 = Activator.CreateInstance(collectionType);
                property.SetValue(instance, obj2, property.PropertyName, false);
            }
            return(obj2);
        }
Example #9
0
        internal static bool TryGetPropertyValue(object source, string sourceProperty, DataServiceProtocolVersion maxProtocolVersion, out BindingPropertyInfo bindingPropertyInfo, out ClientPropertyAnnotation clientProperty, out object propertyValue)
        {
            Type entityType = source.GetType();

            bindingPropertyInfo = GetObservableProperties(entityType, maxProtocolVersion).SingleOrDefault <BindingPropertyInfo>(x => x.PropertyInfo.PropertyName == sourceProperty);
            bool flag = bindingPropertyInfo != null;

            if (!flag)
            {
                clientProperty = GetClientType(entityType, maxProtocolVersion).GetProperty(sourceProperty, true);
                flag           = clientProperty != null;
                if (!flag)
                {
                    propertyValue = null;
                    return(flag);
                }
                propertyValue = clientProperty.GetValue(source);
                return(flag);
            }
            clientProperty = null;
            propertyValue  = bindingPropertyInfo.PropertyInfo.GetValue(source);
            return(flag);
        }
Example #10
0
        private MaterializeAtom ReadPropertyFromAtom(ClientPropertyAnnotation property)
        {
            DataServiceContext context = (DataServiceContext)this.Source;
            bool merging = context.ApplyingChanges;

            try
            {
                context.ApplyingChanges = true;

                // store the results so that they can be there in the response body.
                Type  elementType = property.IsEntityCollection ? property.EntityCollectionItemType : property.NullablePropertyType;
                IList results     = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType));

                DataServiceQueryContinuation continuation = null;

                // elementType.ElementType has Nullable stripped away, use nestedType for materializer
                using (MaterializeAtom materializer = this.GetMaterializer(this.plan))
                {
                    Debug.Assert(materializer != null, "materializer != null -- otherwise GetMaterializer() returned null rather than empty");

#if ASTORIA_OPEN_OBJECT
                    object openProperties = null;
#endif
                    // when SetLink to null, we cannot get materializer because have no-content response.
                    if (materializer.IsNoContentResponse() &&
                        property.GetValue(entity) != null &&
                        context.MergeOption != MergeOption.AppendOnly &&
                        context.MergeOption != MergeOption.NoTracking)
                    {
                        property.SetValue(this.entity, null, propertyName, false);
                    }
                    else
                    {
                        foreach (object child in materializer)
                        {
                            if (property.IsEntityCollection)
                            {
                                results.Add(child);
                            }
                            else if (property.IsPrimitiveOrEnumOrComplexCollection)
                            {
                                Debug.Assert(property.PropertyType.IsAssignableFrom(child.GetType()), "Created instance for storing collection items has to be compatible with the actual one.");

                                // Collection materialization rules requires to clear the collection if not null or set the property first and then add the collection items
                                object collectionInstance = property.GetValue(this.entity);
                                if (collectionInstance == null)
                                {
                                    // type of child has been resolved as per rules for collections so it is the correct type to instantiate
                                    collectionInstance = Activator.CreateInstance(child.GetType());

                                    // allowAdd is false - we need to assign instance as the new property value
                                    property.SetValue(this.entity, collectionInstance, this.propertyName, false /* allowAdd? */);
                                }
                                else
                                {
                                    // Clear existing collection
                                    property.ClearBackingICollectionInstance(collectionInstance);
                                }

                                foreach (var collectionItem in (IEnumerable)child)
                                {
                                    Debug.Assert(property.PrimitiveOrComplexCollectionItemType.IsAssignableFrom(collectionItem.GetType()), "Type of materialized collection items have to be compatible with the type of collection items in the actual collection property.");
                                    property.AddValueToBackingICollectionInstance(collectionInstance, collectionItem);
                                }

                                results.Add(collectionInstance);
                            }
                            else
                            {
#if ASTORIA_OPEN_OBJECT
                                property.SetValue(this.entity, child, this.propertyName, ref openProperties, false);
#else
                                // it is either primitive type, complex type or 1..1 navigation property so we just allow setting the value but not adding.
                                property.SetValue(this.entity, child, this.propertyName, false);
                                results.Add(child);
#endif
                            }
                        }
                    }

                    continuation = materializer.GetContinuation(null);
                }

                return(MaterializeAtom.CreateWrapper(context, results, continuation));
            }
            finally
            {
                context.ApplyingChanges = merging;
            }
        }
Example #11
0
 private void MergeLists(MaterializerEntry entry, ClientPropertyAnnotation property, IEnumerable list, Uri nextLink, ProjectionPlan plan)
 {
     if ((entry.ShouldUpdateFromPayload && (property.NullablePropertyType == list.GetType())) && (property.GetValue(entry.ResolvedObject) == null))
     {
         property.SetValue(entry.ResolvedObject, list, property.PropertyName, false);
         this.FoundNextLinkForCollection(list, nextLink, plan);
         foreach (object obj2 in list)
         {
             this.log.AddedLink(entry, property.PropertyName, obj2);
         }
     }
     else
     {
         this.ApplyItemsToCollection(entry, property, list, nextLink, plan);
     }
 }
Example #12
0
        protected static void ApplyDataValue(ClientTypeAnnotation type, ODataProperty property, bool ignoreMissingProperties, System.Data.Services.Client.ResponseInfo responseInfo, object instance)
        {
            ClientPropertyAnnotation annotation = type.GetProperty(property.Name, ignoreMissingProperties);

            if (annotation != null)
            {
                if (annotation.IsPrimitiveOrComplexCollection)
                {
                    if (property.Value == null)
                    {
                        throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Collection_NullCollectionNotSupported(property.Name));
                    }
                    if (property.Value is string)
                    {
                        throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MixedTextWithComment);
                    }
                    if (property.Value is ODataComplexValue)
                    {
                        throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidCollectionItem(property.Name));
                    }
                    object obj2 = annotation.GetValue(instance);
                    if (obj2 == null)
                    {
                        obj2 = CreateCollectionInstance(property, annotation.PropertyType, responseInfo);
                        annotation.SetValue(instance, obj2, property.Name, false);
                    }
                    else
                    {
                        annotation.ClearBackingICollectionInstance(obj2);
                    }
                    ApplyCollectionDataValues(property, ignoreMissingProperties, responseInfo, obj2, annotation.PrimitiveOrComplexCollectionItemType, new Action <object, object>(annotation.AddValueToBackingICollectionInstance));
                }
                else
                {
                    object            obj3   = property.Value;
                    ODataComplexValue value2 = obj3 as ODataComplexValue;
                    if ((obj3 != null) && (value2 != null))
                    {
                        if (!annotation.EdmProperty.Type.IsComplex())
                        {
                            throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_ExpectingSimpleValue);
                        }
                        bool                 flag  = false;
                        ClientEdmModel       model = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion);
                        ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(annotation.PropertyType));
                        object               obj4 = annotation.GetValue(instance);
                        if (obj4 == null)
                        {
                            obj4 = clientTypeAnnotation.CreateInstance();
                            flag = true;
                        }
                        MaterializeDataValues(clientTypeAnnotation, value2.Properties, ignoreMissingProperties);
                        ApplyDataValues(clientTypeAnnotation, value2.Properties, ignoreMissingProperties, responseInfo, obj4);
                        if (flag)
                        {
                            annotation.SetValue(instance, obj4, property.Name, true);
                        }
                    }
                    else
                    {
                        MaterializePrimitiveDataValue(annotation.NullablePropertyType, property);
                        annotation.SetValue(instance, property.GetMaterializedValue(), property.Name, true);
                    }
                }
            }
        }
Example #13
0
        private MaterializeAtom ReadPropertyFromAtom(EntityDescriptor box, ClientPropertyAnnotation property)
        {
            MaterializeAtom    atom2;
            DataServiceContext source = (DataServiceContext)base.Source;
            bool applyingChanges      = source.ApplyingChanges;

            try
            {
                source.ApplyingChanges = true;
                bool   flag2           = EntityStates.Deleted == box.State;
                bool   instanceCreated = false;
                object instance        = null;
                if (property.IsEntityCollection)
                {
                    instance = this.GetCollectionInstance(property, out instanceCreated);
                }
                Type  type    = property.IsEntityCollection ? property.EntityCollectionItemType : property.NullablePropertyType;
                IList results = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(new Type[] { type }));
                DataServiceQueryContinuation continuation = null;
                using (MaterializeAtom atom = base.GetMaterializer(this.plan))
                {
                    bool flag4 = property.EdmProperty.PropertyKind == EdmPropertyKind.Navigation;
                    int  num   = 0;
                    foreach (object obj3 in atom)
                    {
                        if (property.IsEntityCollection)
                        {
                            property.SetValue(instance, obj3, this.propertyName, true);
                            results.Add(obj3);
                        }
                        else if (property.IsPrimitiveOrComplexCollection)
                        {
                            object obj4 = property.GetValue(this.entity);
                            if (obj4 == null)
                            {
                                obj4 = Activator.CreateInstance(obj3.GetType());
                                property.SetValue(this.entity, obj4, this.propertyName, false);
                            }
                            else
                            {
                                property.ClearBackingICollectionInstance(obj4);
                            }
                            foreach (object obj5 in (IEnumerable)obj3)
                            {
                                property.AddValueToBackingICollectionInstance(obj4, obj5);
                            }
                            results.Add(obj4);
                        }
                        else
                        {
                            property.SetValue(this.entity, obj3, this.propertyName, false);
                            results.Add(obj3);
                        }
                        num++;
                        if (((obj3 != null) && (MergeOption.NoTracking != atom.MergeOptionValue)) && flag4)
                        {
                            if (flag2)
                            {
                                source.DeleteLink(this.entity, this.propertyName, obj3);
                            }
                            else
                            {
                                source.AttachLink(this.entity, this.propertyName, obj3, atom.MergeOptionValue);
                            }
                        }
                    }
                    continuation = atom.GetContinuation(null);
                    Util.SetNextLinkForCollection(property.IsEntityCollection ? instance : this.entity, continuation);
                }
                if (instanceCreated)
                {
                    property.SetValue(this.entity, instance, this.propertyName, false);
                }
                atom2 = MaterializeAtom.CreateWrapper(source, results, continuation);
            }
            finally
            {
                source.ApplyingChanges = applyingChanges;
            }
            return(atom2);
        }