public virtual void SetValue(object targetResource, string propertyName, object propertyValue) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource"); targetResource = token.Resource; token.PendingPropertyUpdates[propertyName] = propertyValue; this.pendingChanges.Add(delegate { object generatedValue; Type t = targetResource.GetType(); PropertyInfo pi = t.GetProperty(propertyName); ExceptionUtilities.CheckObjectNotNull(pi, "Unable to find property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name }); if (this.TryGetStoreGeneratedValue(GetResourceTypeFullName(t), propertyName, out generatedValue)) { propertyValue = generatedValue; } if (this.IsCollectionProperty(pi)) { ExceptionUtilities.CheckObjectNotNull(propertyValue, "Collection property value was null", new object[0]); IEnumerable enumerable = propertyValue as IEnumerable; ExceptionUtilities.CheckObjectNotNull(enumerable, "Collection property value was not an enumerable", new object[0]); this.SetCollectionPropertyValue(targetResource, pi, enumerable); } else { propertyValue = UpdatableToken.ResolveIfToken(propertyValue); pi.SetValue(targetResource, propertyValue, null); } }); }
/// <summary> /// Resets the value of the given resource to its default value /// </summary> /// <param name="resource">resource whose value needs to be reset</param> /// <returns>same resource with its value reset</returns> public virtual object ResetResource(object resource) { ExceptionUtilities.CheckArgumentNotNull(resource, "resource"); var token = UpdatableToken.AssertIsToken(resource, "resource"); resource = token.Resource; // create a new token to return token = new UpdatableToken(resource); object newInstance = Activator.CreateInstance(resource.GetType()); ExceptionUtilities.CheckObjectNotNull(newInstance, "Cannot reset resource because unable to creating new instance of type '{0}' returns null", resource.GetType().Name); string[] propertiesToReset = this.ReflectionMetadataHelper.GetPropertiesToReset(GetResourceTypeFullName(resource.GetType())); // We must only reset values of scalar, scalar Collection, complex, and complexCollection properties, the key and navigations must stay the same foreach (string propertyToReset in propertiesToReset) { PropertyInfo pi = newInstance.GetType().GetProperty(propertyToReset); ExceptionUtilities.CheckObjectNotNull(pi, "Cannot reset resource because unable to find property '{0}'", propertyToReset); object newValue = pi.GetValue(newInstance, null); this.pendingChanges.Add(() => pi.SetValue(resource, newValue, null)); token.PendingPropertyUpdates[propertyToReset] = newValue; } return(token); }
/// <summary> /// Gets the value of the given property on the target object /// </summary> /// <param name="targetResource">target object which defines the property</param> /// <param name="propertyName">name of the property whose value needs to be updated</param> /// <returns>the value of the property for the given target resource</returns> public virtual object GetValue(object targetResource, string propertyName) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); // resolve the token, and return a pending value if there is one // NOTE: this code is specifically to handle cases of mapped complex-type values, because the product does not cache the // value returned by CreateResource so we need to take into account any pending updates, or we risk returning stale data var token = UpdatableToken.AssertIsToken(targetResource, "targetResource"); if (token.PendingPropertyUpdates.ContainsKey(propertyName)) { return(token.PendingPropertyUpdates[propertyName]); } targetResource = token.Resource; PropertyInfo pi = targetResource.GetType().GetProperty(propertyName); ExceptionUtilities.CheckObjectNotNull(pi, "Cannot find the property '{0}' on type '{1}'", propertyName, targetResource.GetType().Name); var value = pi.GetValue(targetResource, null); // NOTE: we need to token-ize any complex values before returning them // we should have a better way of telling a type is complex, but this works for now if (value != null && pi.PropertyType.Assembly == this.GetType().Assembly) { ExceptionUtilities.Assert(!this.ReflectionMetadataHelper.IsTypeAnEntityType(pi.PropertyType), "GetValue should never be called for reference properties. Type was '{0}', property was '{1}'", pi.PropertyType.FullName, propertyName); value = new UpdatableToken(value); } return(value); }
/// <summary> /// Adds the given value to the collection /// </summary> /// <param name="targetResource">target object which defines the property</param> /// <param name="propertyName">name of the property whose value needs to be updated</param> /// <param name="resourceToBeAdded">value of the property which needs to be added</param> public virtual void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); ExceptionUtilities.CheckArgumentNotNull(resourceToBeAdded, "resourceToBeAdded"); // resolve the target token var targetToken = UpdatableToken.AssertIsToken(targetResource, "targetResource"); targetResource = targetToken.Resource; // resolve the added token resourceToBeAdded = UpdatableToken.AssertIsTokenAndResolve(resourceToBeAdded, "resourceToBeAdded"); // All resource set reference properties must be of type IList<T> where T is the type of an entitySet // Note that we don't support bi-directional relationships so we only handle the one resource set reference property in isolation. IList list = this.GetValue(targetToken, propertyName) as IList; ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", propertyName, targetResource.GetType().Name); this.pendingChanges.Add(() => { list.Add(resourceToBeAdded); }); }
public virtual void SetReference(object targetResource, string propertyName, object propertyValue) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); if (propertyValue != null) { UpdatableToken.AssertIsToken(propertyValue, "propertyValue"); } this.SetValue(targetResource, propertyName, propertyValue); }
public virtual void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); ExceptionUtilities.CheckArgumentNotNull(resourceToBeRemoved, "resourceToBeRemoved"); UpdatableToken.AssertIsToken(targetResource, "targetResource"); resourceToBeRemoved = UpdatableToken.AssertIsTokenAndResolve(resourceToBeRemoved, "resourceToBeRemoved"); IList list = this.GetValue(targetResource, propertyName) as IList; ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", new object[] { propertyName, targetResource.GetType().Name }); this.pendingChanges.Add(delegate { list.Remove(resourceToBeRemoved); }); }
/// <summary> /// Sets the value of the given reference property on the target object /// </summary> /// <param name="targetResource">target object which defines the property</param> /// <param name="propertyName">name of the property whose value needs to be updated</param> /// <param name="propertyValue">value of the property</param> public virtual void SetReference(object targetResource, string propertyName, object propertyValue) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); if (propertyValue != null) { UpdatableToken.AssertIsToken(propertyValue, "propertyValue"); } // Note that we don't support bi-directional relationships so we only handle the one resource reference property in isolation. // Our reference properties are just like normal properties we just set the property value to the new value // we don't perform any special actions for references. // So just call the SetValue which will do exactly that. this.SetValue(targetResource, propertyName, propertyValue); }
/// <summary> /// Sets the value of the given property on the target object /// </summary> /// <param name="targetResource">target object which defines the property</param> /// <param name="propertyName">name of the property whose value needs to be updated</param> /// <param name="propertyValue">value of the property</param> public virtual void SetValue(object targetResource, string propertyName, object propertyValue) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); var token = UpdatableToken.AssertIsToken(targetResource, "targetResource"); targetResource = token.Resource; // note that propertyValue might be a token itself, but GetValue will simply return whatever is stored in the token token.PendingPropertyUpdates[propertyName] = propertyValue; // Add a pending change to modify the value of the property this.pendingChanges.Add(() => { Type t = targetResource.GetType(); PropertyInfo pi = t.GetProperty(propertyName); ExceptionUtilities.CheckObjectNotNull(pi, "Unable to find property '{0}' on type '{1}'", propertyName, targetResource.GetType().Name); string entitySetName = this.ReflectionMetadataHelper.FindSetNameForType(t); object generatedValue; if (this.TryGetStoreGeneratedValue(entitySetName, GetResourceTypeFullName(t), propertyName, out generatedValue)) { propertyValue = generatedValue; } if (this.IsCollectionProperty(pi)) { ExceptionUtilities.CheckObjectNotNull(propertyValue, "Collection property value was null"); var enumerable = propertyValue as IEnumerable; ExceptionUtilities.CheckObjectNotNull(enumerable, "Collection property value was not an enumerable"); this.SetCollectionPropertyValue(targetResource, pi, enumerable); } else { propertyValue = UpdatableToken.ResolveIfToken(propertyValue); pi.SetValue(targetResource, propertyValue, null); } }); }
public virtual object ResetResource(object resource) { ExceptionUtilities.CheckArgumentNotNull(resource, "resource"); UpdatableToken token = UpdatableToken.AssertIsToken(resource, "resource"); resource = token.Resource; token = new UpdatableToken(resource); object newInstance = Activator.CreateInstance(resource.GetType()); ExceptionUtilities.CheckObjectNotNull(newInstance, "Cannot reset resource because unable to creating new instance of type '{0}' returns null", new object[] { resource.GetType().Name }); foreach (string propertyToReset in this.MetadataHelper.GetPropertiesToReset(GetResourceTypeFullName(resource.GetType()))) { PropertyInfo pi = newInstance.GetType().GetProperty(propertyToReset); ExceptionUtilities.CheckObjectNotNull(pi, "Cannot reset resource because unable to find property '{0}'", new object[] { propertyToReset }); object newValue = pi.GetValue(newInstance, null); this.pendingChanges.Add(delegate { pi.SetValue(resource, newValue, null); }); token.PendingPropertyUpdates[propertyToReset] = newValue; } return(token); }
public virtual object GetValue(object targetResource, string propertyName) { ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource"); ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName"); UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource"); if (token.PendingPropertyUpdates.ContainsKey(propertyName)) { return(token.PendingPropertyUpdates[propertyName]); } targetResource = token.Resource; PropertyInfo pi = targetResource.GetType().GetProperty(propertyName); ExceptionUtilities.CheckObjectNotNull(pi, "Cannot find the property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name }); object value = pi.GetValue(targetResource, null); if ((value != null) && (pi.PropertyType.Assembly == base.GetType().Assembly)) { ExceptionUtilities.Assert(!this.MetadataHelper.IsTypeAnEntityType(pi.PropertyType), "GetValue should never be called for reference properties. Type was '{0}', property was '{1}'", new object[] { pi.PropertyType.FullName, propertyName }); value = new UpdatableToken(value); } return(value); }