Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit of the Windows client SDK for Mobile Services

  • Loading branch information...
commit ad64844f68d0fee7395abd7868f54b8a35607639 0 parents
@paulbatum paulbatum authored
Showing with 16,386 additions and 0 deletions.
  1. +176 −0 LICENSE.txt
  2. +5 −0 sdk/windows/.gitignore
  3. +198 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/IMobileServiceTable.Generic.cs
  4. +62 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/IMobileServiceTable.Managed.cs
  5. +90 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceClient.Managed.cs
  6. +41 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceInvalidOperationException.cs
  7. +480 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceTable.Generic.cs
  8. +89 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceTable.Managed.cs
  9. +209 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Microsoft.Azure.Zumo.Windows.Managed.csproj
  10. +16 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Properties/AssemblyInfo.cs
  11. +144 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Resources.cs
  12. +798 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/CollectionView/MobileServiceCollectionView.cs
  13. +36 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/CollectionView/VectorChangedEventArgs.cs
  14. +511 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/FilterBuildingExpressionVisitor.cs
  15. +25 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/ITotalCountProvider.cs
  16. +324 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/MobileServiceTableQuery.cs
  17. +169 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/MobileServiceTableQueryDescription.cs
  18. +324 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/MobileServiceTableQueryTranslator.cs
  19. +161 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/PartialEvaulator.cs
  20. +69 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/TotalCountEnumerable.cs
  21. +45 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/TotalCountList.cs
  22. +109 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Query/VisitorHelper.cs
  23. +23 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Serialization/DataMemberJsonConverterAttribute.cs
  24. +21 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Serialization/DataTableAttribute.cs
  25. +36 −0 ...dows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Serialization/ICustomMobileServiceTableSerialization.cs
  26. +31 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Serialization/IDataMemberJsonConverter.cs
  27. +242 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Serialization/MobileServiceTableSerializer.cs
  28. +129 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Serialization/SerializableMember.cs
  29. +290 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/Serialization/SerializableType.cs
  30. +545 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/TypeExtensions.cs
  31. +60 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/IMobileServiceTable.WinMD.cs
  32. +25 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/IMobileServiceTable.cs
  33. +424 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/JsonExtensions.cs
  34. +52 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/MobileServiceClient.WinMD.cs
  35. +419 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/MobileServiceClient.cs
  36. +72 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/MobileServiceTable.WinMD.cs
  37. +266 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/MobileServiceTable.cs
  38. +31 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/MobileServiceUser.cs
  39. +72 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/Resources.cs
  40. +45 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Core/TypeExtensions.cs
  41. BIN  sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/GlobalSuppressions.cs
  42. +144 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Microsoft.Azure.Zumo.Windows.WinMD.csproj
  43. +10 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/Properties/AssemblyInfo.cs
  44. +113 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/ComposedServiceFilter.cs
  45. +53 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/IServiceFilter.cs
  46. +29 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/IServiceFilterContinuation.cs
  47. +73 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/IServiceFilterRequest.cs
  48. +46 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/IServiceFilterResponse.cs
  49. +52 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/ServiceFilter.cs
  50. +138 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/ServiceFilterRequest.cs
  51. +97 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/ServiceFilterResponse.cs
  52. +132 −0 sdk/windows/src/Microsoft.Azure.Zumo.Windows.WinMD/ServiceFilter/ServiceFilterResponseStatus.cs
  53. +27 −0 sdk/windows/src/ZumoAssemblyInfo.cs
  54. +18 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/App.xaml
  55. +87 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/App.xaml.cs
  56. BIN  sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Assets/Logo.png
  57. BIN  sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Assets/SmallLogo.png
  58. BIN  sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Assets/SplashScreen.png
  59. BIN  sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Assets/StoreLogo.png
  60. +1,007 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Common/StandardStyles.xaml
  61. +89 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/MainPage.xaml
  62. +46 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/MainPage.xaml.cs
  63. +191 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Microsoft.Azure.Zumo.Windows.CSharp.Test.csproj
  64. BIN  ...ows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Microsoft.Azure.Zumo.Windows.CSharp.Test_TemporaryKey.pfx
  65. +42 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Package.appxmanifest
  66. +9 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Properties/AssemblyInfo.cs
  67. +453 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/TestPage.xaml
  68. +164 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/TestPage.xaml.cs
  69. +52 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/AsyncTestMethodAsyncAction.cs
  70. +16 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/AsyncTestMethodAttribute.cs
  71. +22 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/ExcludeTestAttribute.cs
  72. +16 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/FunctionalTestAttribute.cs
  73. +47 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/GroupDescription.cs
  74. +22 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/TagAttribute.cs
  75. +75 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/TestBase.cs
  76. +68 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/TestDescription.cs
  77. +102 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/TestDiscovery.cs
  78. +42 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/TestMethodAsyncAction.cs
  79. +16 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/TestMethodAttribute.cs
  80. +59 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Framework/TestServiceFilter.cs
  81. +105 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/BloggingTest.cs
  82. +47 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/Book.cs
  83. +62 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/ConnectionFailures.cs
  84. +37 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/DataSourceTest.cs
  85. +491 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/DataTypesTest.cs
  86. +177 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/DateTests.cs
  87. +60 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/FunctionalTestBase.cs
  88. +352 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/QueryingTest.cs
  89. +202 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/ToDoTest.cs
  90. +88 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Functional/VersioningTest.cs
  91. +250 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Unit/JsonExtensions.Test.cs
  92. +468 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Unit/TypeExtensions.Test.cs
  93. +505 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Unit/ZumoQuery.Test.cs
  94. +245 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Unit/ZumoSerializer.Tests.cs
  95. +421 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Unit/ZumoService.Test.cs
  96. +24 −0 sdk/windows/test/Microsoft.Azure.Zumo.Windows.CSharp.Test/Tests/Unit/ZumoUser.Test.cs
  97. +44 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/ActionContinuation.cs
  98. +287 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/Assert.cs
  99. +66 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/FunctionalTestFilter.cs
  100. +25 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/IAsyncExecution.cs
  101. +27 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/IContinuation.cs
  102. +83 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/ITestReporter.cs
  103. +144 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/Microsoft.Azure.Zumo.Windows.Test.csproj
  104. +14 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/Properties/AssemblyInfo.cs
  105. +373 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/Tagging/TagManager.ExpressionEvaluator.cs
  106. +53 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/Tagging/TagManager.Tags.cs
  107. +163 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/Tagging/TagManager.cs
  108. +51 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/Tagging/TagTestFilter.cs
  109. +57 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/TestFilter.cs
  110. +57 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/TestGroup.cs
  111. +268 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/TestHarness.cs
  112. +84 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/TestMethod.cs
  113. +107 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/TestSettings.cs
  114. +79 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/WinJS/Formatter.cs
  115. +19 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/WinJS/MessageEventArgs.cs
  116. +57 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/WinJS/PromiseAsyncExecution.cs
  117. +66 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/WinJS/PromiseAsyncExecutionEventArgs.cs
  118. +179 −0 sdk/windows/tools/Microsoft.Azure.Zumo.Windows.Test/WinJS/TestReporter.cs
  119. +28 −0 sdk/windows/tools/Zumo.settings.targets
  120. +100 −0 sdk/windows/win8sdk.sln
176 LICENSE.txt
@@ -0,0 +1,176 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
5 sdk/windows/.gitignore
@@ -0,0 +1,5 @@
+bin/
+obj/
+*.user
+*.suo
+AppPackages/
198 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/IMobileServiceTable.Generic.cs
@@ -0,0 +1,198 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Windows.Data.Json;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// Provides operations on a table for a Mobile Service.
+ /// </summary>
+ /// <typeparam name="T">
+ /// The type of elements in the table (which implies the table).
+ /// </typeparam>
+ public partial interface IMobileServiceTable<T> : IMobileServiceTable
+ {
+ /// <summary>
+ /// Get the elements of a table based using a query.
+ /// </summary>
+ /// <typeparam name="U">
+ /// The type of element returned by the query.
+ /// </typeparam>
+ /// <param name="query">The query to execute.</param>
+ /// <returns>Elements of the table.</returns>
+ [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T", Justification = "Part of the LINQ query pattern")]
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U", Justification = "Part of the LINQ query pattern")]
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Generic are not nested when used via async.")]
+ Task<IEnumerable<U>> ReadAsync<U>(MobileServiceTableQuery<U> query);
+
+ /// <summary>
+ /// Get the elements in a table.
+ /// </summary>
+ /// <returns>The elements in the table.</returns>
+ /// <remarks>
+ /// This call will not handle paging, etc., for you.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "It does not appear nested when used via the async pattern.")]
+ Task<IEnumerable<T>> ReadAsync();
+
+ /// <summary>
+ /// Lookup an element from a table by its ID.
+ /// </summary>
+ /// <param name="id">The ID of the element.</param>
+ /// <returns>The desired element.</returns>
+ Task<T> LookupAsync(object id);
+
+ /// <summary>
+ /// Refresh the current instance with the latest values from the
+ /// table.
+ /// </summary>
+ /// <param name="instance">The instance to refresh.</param>
+ /// <returns>
+ /// A task that will complete when the refresh has finished.
+ /// </returns>
+ Task RefreshAsync(T instance);
+
+ /// <summary>
+ /// Insert a new instance into the table.
+ /// </summary>
+ /// <param name="instance">The instance to insert.</param>
+ /// <returns>
+ /// A task that will complete when the insertion has finished.
+ /// </returns>
+ Task InsertAsync(T instance);
+
+ /// <summary>
+ /// Updates an instance in the table.
+ /// </summary>
+ /// <param name="instance">The instance to update.</param>
+ /// <returns>
+ /// A task that will complete when the update has finished.
+ /// </returns>
+ Task UpdateAsync(T instance);
+
+ /// <summary>
+ /// Delete an instance from the table.
+ /// </summary>
+ /// <param name="instance">The instance to delete.</param>
+ /// <returns>
+ /// A task that will complete when the delete has finished.
+ /// </returns>
+ Task DeleteAsync(T instance);
+
+ /// <summary>
+ /// Creates a query by applying the specified filter predicate.
+ /// </summary>
+ /// <param name="predicate">The filter predicate.</param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ MobileServiceTableQuery<T> Where(Expression<Func<T, bool>> predicate);
+
+ /// <summary>
+ /// Creates a query by applying the specified selection.
+ /// </summary>
+ /// <typeparam name="U">
+ /// Type representing the projected result of the query.
+ /// </typeparam>
+ /// <param name="selector">The selector function.</param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Naming", "CA1715:IdentifiersShouldHaveCorrectPrefix", MessageId = "T", Justification = "Standard for LINQ")]
+ [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Select", Justification = "Part of the LINQ query pattern.")]
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U", Justification = "Standard for LINQ")]
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ MobileServiceTableQuery<U> Select<U>(Expression<Func<T, U>> selector);
+
+ /// <summary>
+ /// Creates a query by applying the specified ascending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ MobileServiceTableQuery<T> OrderBy<TKey>(Expression<Func<T, TKey>> keySelector);
+
+ /// <summary>
+ /// Creates a query by applying the specified descending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ MobileServiceTableQuery<T> OrderByDescending<TKey>(Expression<Func<T, TKey>> keySelector);
+
+ /// <summary>
+ /// Creates a query by applying the specified ascending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ MobileServiceTableQuery<T> ThenBy<TKey>(Expression<Func<T, TKey>> keySelector);
+
+ /// <summary>
+ /// Creates a query by applying the specified descending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ MobileServiceTableQuery<T> ThenByDescending<TKey>(Expression<Func<T, TKey>> keySelector);
+
+ /// <summary>
+ /// Creates a query by applying the specified skip clause.
+ /// </summary>
+ /// <param name="count">The number to skip.</param>
+ /// <returns>A query against the table.</returns>
+ MobileServiceTableQuery<T> Skip(int count);
+
+ /// <summary>
+ /// Creates a query by applying the specified take clause.
+ /// </summary>
+ /// <param name="count">The number to take.</param>
+ /// <returns>A query against the table.</returns>
+ MobileServiceTableQuery<T> Take(int count);
+
+ /// <summary>
+ /// Gets the elements of the table asynchronously.
+ /// </summary>
+ /// <returns>The table elements results as a sequence.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Not nested when used via async pattern.")]
+ Task<IEnumerable<T>> ToEnumerableAsync();
+
+ /// <summary>
+ /// Gets the elements of the table asynchronously and return the
+ /// results in a new List.
+ /// </summary>
+ /// <returns>The table elements results as a List.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Not nested when used via async pattern.")]
+ Task<List<T>> ToListAsync();
+
+ /// <summary>
+ /// Create a new collection view based on the query.
+ /// </summary>
+ /// <returns>The collection view.</returns>
+ MobileServiceCollectionView<T> ToCollectionView();
+ }
+}
62 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/IMobileServiceTable.Managed.cs
@@ -0,0 +1,62 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+using Windows.Data.Json;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// Provides operations on tables for a Mobile Service.
+ /// </summary>
+ public partial interface IMobileServiceTable
+ {
+ /// <summary>
+ /// Excute a query against a table.
+ /// </summary>
+ /// <param name="query">
+ /// An OData query to execute.
+ /// </param>
+ /// <returns>
+ /// A task that will return with results when the query finishes.
+ /// </returns>
+ [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "1#", Justification = "Query is both a verb and noun.")]
+ Task<IJsonValue> ReadAsync(string query);
+
+ /// <summary>
+ /// Insert a new object into a table.
+ /// </summary>
+ /// <param name="instance">
+ /// The instance to insert into the table.
+ /// </param>
+ /// <returns>
+ /// A task that will complete when the insert finishes.
+ /// </returns>
+ Task<IJsonValue> InsertAsync(JsonObject instance);
+
+ /// <summary>
+ /// Update an object in a given table.
+ /// </summary>
+ /// <param name="instance">
+ /// The instance to update in the table.
+ /// </param>
+ /// <returns>
+ /// A task that will complete when the update finishes.
+ /// </returns>
+ Task<IJsonValue> UpdateAsync(JsonObject instance);
+
+ /// <summary>
+ /// Delete an object from a given table.
+ /// </summary>
+ /// <param name="instance">
+ /// The instance to delete from the table.
+ /// </param>
+ /// <returns>
+ /// A task that will complete when the delete finishes.
+ /// </returns>
+ Task DeleteAsync(JsonObject instance);
+ }
+}
90 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceClient.Managed.cs
@@ -0,0 +1,90 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// Provides basic access to Mobile Services.
+ /// </summary>
+ public sealed partial class MobileServiceClient
+ {
+ /// <summary>
+ /// Initializes a new instance of the MobileServiceClient class.
+ /// </summary>
+ /// <param name="applicationUrl">
+ /// The Url to the Mobile Services application.
+ /// </param>
+ [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification = "Enables easier copy/paste getting started workflow")]
+ public MobileServiceClient(string applicationUrl)
+ : this(new Uri(applicationUrl))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the MobileServiceClient class.
+ /// </summary>
+ /// <param name="applicationUrl">
+ /// The Url to the Mobile Services application.
+ /// </param>
+ /// <param name="applicationKey">
+ /// The application name for the Mobile Services application.
+ /// </param>
+ [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification = "Enables easier copy/paste getting started workflow")]
+ public MobileServiceClient(string applicationUrl, string applicationKey)
+ : this(new Uri(applicationUrl), applicationKey)
+ {
+ }
+
+ /// <summary>
+ /// Log a user into a Mobile Services application given an access
+ /// token.
+ /// </summary>
+ /// <param name="authenticationToken">
+ /// OAuth access token that authenticates the user.
+ /// </param>
+ /// <returns>
+ /// Task that will complete when the user has finished authentication.
+ /// </returns>
+ [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login", Justification = "Login is preferred by design")]
+ public Task<MobileServiceUser> LoginAsync(string authenticationToken)
+ {
+ return this.SendLoginAsync(authenticationToken);
+ }
+
+ /// <summary>
+ /// Gets a reference to a table and its data operations.
+ /// </summary>
+ /// <typeparam name="T">
+ /// The type of the elements in the table. This implies the name of
+ /// the table will either be the type's name or the value of the
+ /// DataTableAttribute applied to the type.
+ /// </typeparam>
+ /// <returns>A reference to the table.</returns>
+ public IMobileServiceTable<T> GetTable<T>()
+ {
+ SerializableType type = SerializableType.Get(typeof(T));
+ return new MobileServiceTable<T>(type.TableName, this);
+ }
+
+ /// <summary>
+ /// Create an exception for an invalid response to a web request.
+ /// </summary>
+ /// <param name="errorMessage">The error message.</param>
+ /// <param name="request">The request.</param>
+ /// <param name="response">The response.</param>
+ private static Exception CreateMobileServiceException(string errorMessage, IServiceFilterRequest request, IServiceFilterResponse response)
+ {
+ Debug.Assert(!string.IsNullOrEmpty(errorMessage), "errorMessage cannot be null or empty!");
+ Debug.Assert(request != null, "request cannot be null!");
+ Debug.Assert(response != null, "response cannot be null!");
+
+ throw new MobileServiceInvalidOperationException(errorMessage, request, response);
+ }
+ }
+}
41 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceInvalidOperationException.cs
@@ -0,0 +1,41 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// Provides additional details of an invalid operation specific to a
+ /// Mobile Service.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors", Justification = "The exception cannot be instantiated by customers.")]
+ public sealed class MobileServiceInvalidOperationException : InvalidOperationException
+ {
+ /// <summary>
+ /// Initializes a new instance of the
+ /// MobileServiceInvalidOperationException class.
+ /// </summary>
+ /// <param name="message">The exception message.</param>
+ /// <param name="request">The originating service request.</param>
+ /// <param name="response">The returned service response.</param>
+ internal MobileServiceInvalidOperationException(string message, IServiceFilterRequest request, IServiceFilterResponse response)
+ : base(message)
+ {
+ this.Request = request;
+ this.Response = response;
+ }
+
+ /// <summary>
+ /// Gets the originating service request.
+ /// </summary>
+ public IServiceFilterRequest Request { get; private set; }
+
+ /// <summary>
+ /// Gets the returned service response.
+ /// </summary>
+ public IServiceFilterResponse Response { get; private set; }
+ }
+}
480 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceTable.Generic.cs
@@ -0,0 +1,480 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Windows.Data.Json;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// Provides operations on tables for a Mobile Service.
+ /// </summary>
+ /// <typeparam name="T">
+ /// The type of elements in the table (which implies the table).
+ /// </typeparam>
+ internal partial class MobileServiceTable<T> : MobileServiceTable, IMobileServiceTable<T>
+ {
+ /// <summary>
+ /// Initializes a new instance of the MobileServiceTables class.
+ /// </summary>
+ /// <param name="tableName">The name of the table.</param>
+ /// <param name="client">
+ /// Reference to the MobileServiceClient associated with this table.
+ /// </param>
+ public MobileServiceTable(string tableName, MobileServiceClient client)
+ : base(tableName, client)
+ {
+ }
+
+ /// <summary>
+ /// Get the elements of a table based using a query.
+ /// </summary>
+ /// <typeparam name="U">
+ /// The type of element returned by the query.
+ /// </typeparam>
+ /// <param name="query">The query to execute.</param>
+ /// <returns>Elements of the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Generic are not nested when used via async.")]
+ public Task<IEnumerable<U>> ReadAsync<U>(MobileServiceTableQuery<U> query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ return EvaluateQueryAsync<U>(this, query.Compile());
+ }
+
+ /// <summary>
+ /// Evaluate a query and return its results.
+ /// </summary>
+ /// <typeparam name="U">
+ /// The type of element returned by the query.
+ /// </typeparam>
+ /// <param name="table">
+ /// Access to MobileServices table operations.
+ /// </param>
+ /// <param name="query">
+ /// The description of the query to evaluate and get the results for.
+ /// </param>
+ /// <returns>Results of the query.</returns>
+ internal static async Task<IEnumerable<U>> EvaluateQueryAsync<U>(IMobileServiceTable<T> table, MobileServiceTableQueryDescription query)
+ {
+ Debug.Assert(query != null, "query cannot be null!");
+ Debug.Assert(table != null, "table cannot be null!");
+
+ // Send the query
+ string odata = query.ToString();
+ IJsonValue response = await table.ReadAsync(odata);
+
+ // Parse the results
+ long totalCount;
+ JsonArray values = MobileServiceTable<T>.GetResponseSequence(response, out totalCount);
+ return new TotalCountEnumerable<U>(
+ totalCount,
+ values.Select(
+ item =>
+ {
+ // Create and fill a new instance of the type we should
+ // deserialize (which is either T or the input param
+ // to the projection that will modify T).
+ object obj = Activator.CreateInstance(query.ProjectionArgumentType ?? typeof(U));
+ MobileServiceTableSerializer.Deserialize(item, obj);
+
+ // Apply the projection to the instance transforming it
+ // as desired
+ if (query.Projection != null)
+ {
+ obj = query.Projection.DynamicInvoke(obj);
+ }
+
+ return (U)obj;
+ }));
+ }
+
+ /// <summary>
+ /// Get the elements in a table.
+ /// </summary>
+ /// <returns>The elements in the table.</returns>
+ /// <remarks>
+ /// This call will not handle paging, etc., for you.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "It does not appear nested when used via the async pattern.")]
+ public async Task<IEnumerable<T>> ReadAsync()
+ {
+ // Need to declare an empty string so the compiler can distinguish
+ // between a null query and a null string
+ string odata = null;
+ IJsonValue response = await this.ReadAsync(odata);
+
+ // Get the response as an array
+ long totalCount;
+ JsonArray values = GetResponseSequence(response, out totalCount);
+
+ // Deserialize the values and associate the query context
+ return new TotalCountEnumerable<T>(
+ totalCount,
+ values.Select(MobileServiceTableSerializer.Deserialize<T>));
+ }
+
+ /// <summary>
+ /// Parse a JSON response into a sequence of elements and also return
+ /// the count of objects. This method abstracts out the differences
+ /// between a raw array response and an inline count response.
+ /// </summary>
+ /// <param name="response">The JSON response.</param>
+ /// <param name="totalCount">
+ /// The total count as requested via the IncludeTotalCount method.
+ /// </param>
+ /// <returns>The response as a JSON array.</returns>
+ internal static JsonArray GetResponseSequence(IJsonValue response, out long totalCount)
+ {
+ double? inlineCount = null;
+
+ // Try and get the values as an array
+ JsonArray values = response.AsArray();
+ if (values == null)
+ {
+ // Otherwise try and get the values from the results property
+ // (which is the case when we retrieve the count inline)
+ values = response.Get(InlineCountResultsKey).AsArray();
+ inlineCount = response.Get(InlineCountCountKey).AsNumber();
+ if (values == null)
+ {
+ throw new InvalidOperationException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ Resources.MobileServiceTables_GetResponseSequence_ExpectedArray,
+ (response ?? JsonExtensions.Null()).Stringify()));
+ }
+ }
+
+ // Get the count via the inline count or default an unspecified
+ // count to -1
+ totalCount = inlineCount != null ?
+ (long)inlineCount.Value :
+ -1L;
+
+ return values;
+ }
+
+ /// <summary>
+ /// Get an element from a table by its ID.
+ /// </summary>
+ /// <param name="id">The ID of the element.</param>
+ /// <returns>The desired element.</returns>
+ public async Task<T> LookupAsync(object id)
+ {
+ // TODO: At some point in the future this will be involved in our
+ // caching story and relationships across tables via foreign
+ // keys.
+
+ IJsonValue value = await this.SendLookupAsync(id);
+ return MobileServiceTableSerializer.Deserialize<T>(value.AsObject());
+ }
+
+ /// <summary>
+ /// Refresh the current instance with the latest values from the
+ /// table.
+ /// </summary>
+ /// <param name="instance">The instance to refresh.</param>
+ /// <returns>
+ /// A task that will complete when the refresh has finished.
+ /// </returns>
+ public async Task RefreshAsync(T instance)
+ {
+ if (instance == null)
+ {
+ throw new ArgumentNullException("instance");
+ }
+
+ // Only refresh if it's already on the server
+ SerializableType type = SerializableType.Get(typeof(T));
+ object id = type.IdMember.GetValue(instance);
+ if (!SerializableType.IsDefaultIdValue(id))
+ {
+ // Get the latest version of this element
+ JsonObject obj = await this.GetSingleValueAsync(id);
+
+ // Deserialize that value back into the current instance
+ MobileServiceTableSerializer.Deserialize(obj, instance);
+ }
+ }
+
+ /// <summary>
+ /// Get an element from a table by its ID.
+ /// </summary>
+ /// <param name="id">The ID of the element.</param>
+ /// <returns>The desired element as JSON object.</returns>
+ private async Task<JsonObject> GetSingleValueAsync(object id)
+ {
+ // Create a query for just this item
+ string query = string.Format(
+ CultureInfo.InvariantCulture,
+ "$filter={0} eq {1}",
+ IdPropertyName,
+ TypeExtensions.ToODataConstant(id));
+
+ // Send the query
+ IJsonValue response = await this.ReadAsync(query);
+
+ // Get the first element in the response
+ JsonObject obj = response.AsObject();
+ if (obj == null)
+ {
+ JsonArray array = response.AsArray();
+ if (array != null && array.Count > 0)
+ {
+ obj = array.FirstOrDefault().AsObject();
+ }
+ }
+
+ if (obj == null)
+ {
+ throw new InvalidOperationException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ Resources.MobileServiceTables_GetSingleValueAsync_NotSingleObject,
+ (response ?? JsonExtensions.Null()).Stringify()));
+ }
+
+ return obj;
+ }
+
+ /// <summary>
+ /// Insert a new instance into the table.
+ /// </summary>
+ /// <param name="instance">The instance to insert.</param>
+ /// <returns>
+ /// A task that will complete when the insertion has finished.
+ /// </returns>
+ public async Task InsertAsync(T instance)
+ {
+ if (instance == null)
+ {
+ throw new ArgumentNullException("instance");
+ }
+
+ // Serialize the instance
+ JsonObject value = MobileServiceTableSerializer.Serialize(instance).AsObject();
+
+ // Send the request
+ IJsonValue response = await this.InsertAsync(value);
+
+ // Deserialize the response back into the instance in case any
+ // server scripts changed values of the instance.
+ MobileServiceTableSerializer.Deserialize(response, instance);
+ }
+
+ /// <summary>
+ /// Updates an instance in the table.
+ /// </summary>
+ /// <param name="instance">The instance to update.</param>
+ /// <returns>
+ /// A task that will complete when the update has finished.
+ /// </returns>
+ public async Task UpdateAsync(T instance)
+ {
+ if (instance == null)
+ {
+ throw new ArgumentNullException("instance");
+ }
+
+ // Serialize the instance
+ JsonObject value = MobileServiceTableSerializer.Serialize(instance).AsObject();
+
+ // Send the request
+ IJsonValue response = await this.UpdateAsync(value);
+
+ // Deserialize the response back into the instance in case any
+ // server scripts changed values of the instance.
+ MobileServiceTableSerializer.Deserialize(response, instance);
+ }
+
+ /// <summary>
+ /// Delete an instance from the table.
+ /// </summary>
+ /// <param name="instance">The instance to delete.</param>
+ /// <returns>
+ /// A task that will complete when the delete has finished.
+ /// </returns>
+ public async Task DeleteAsync(T instance)
+ {
+ if (instance == null)
+ {
+ throw new ArgumentNullException("instance");
+ }
+
+ // Serialize the instance
+ JsonObject value = MobileServiceTableSerializer.Serialize(instance).AsObject();
+
+ // Send the request
+ await this.DeleteAsync(value);
+
+ // Clear the instance ID since it's no longer associated with that
+ // ID on the server (note that reflection is goodly enough to turn
+ // null into the correct value for us).
+ SerializableType type = SerializableType.Get(typeof(T));
+ type.IdMember.SetValue(instance, null);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified filter predicate.
+ /// </summary>
+ /// <param name="predicate">The filter predicate.</param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ public MobileServiceTableQuery<T> Where(Expression<Func<T, bool>> predicate)
+ {
+ return new MobileServiceTableQuery<T>(this).Where(predicate);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified selection.
+ /// </summary>
+ /// <typeparam name="U">
+ /// Type representing the projected result of the query.
+ /// </typeparam>
+ /// <param name="selector">The selector function.</param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U", Justification = "Standard for LINQ")]
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ public MobileServiceTableQuery<U> Select<U>(Expression<Func<T, U>> selector)
+ {
+ return new MobileServiceTableQuery<T>(this).Select(selector);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified ascending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ public MobileServiceTableQuery<T> OrderBy<TKey>(Expression<Func<T, TKey>> keySelector)
+ {
+ return new MobileServiceTableQuery<T>(this).OrderBy(keySelector);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified descending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ public MobileServiceTableQuery<T> OrderByDescending<TKey>(Expression<Func<T, TKey>> keySelector)
+ {
+ return new MobileServiceTableQuery<T>(this).OrderByDescending(keySelector);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified ascending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ public MobileServiceTableQuery<T> ThenBy<TKey>(Expression<Func<T, TKey>> keySelector)
+ {
+ return new MobileServiceTableQuery<T>(this).ThenBy(keySelector);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified descending order clause.
+ /// </summary>
+ /// <typeparam name="TKey">
+ /// The type of the member being ordered by.
+ /// </typeparam>
+ /// <param name="keySelector">
+ /// The expression selecting the member to order by.
+ /// </param>
+ /// <returns>A query against the table.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Part of the LINQ query pattern.")]
+ public MobileServiceTableQuery<T> ThenByDescending<TKey>(Expression<Func<T, TKey>> keySelector)
+ {
+ return new MobileServiceTableQuery<T>(this).ThenByDescending(keySelector);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified skip clause.
+ /// </summary>
+ /// <param name="count">The number to skip.</param>
+ /// <returns>A query against the table.</returns>
+ public MobileServiceTableQuery<T> Skip(int count)
+ {
+ return new MobileServiceTableQuery<T>(this).Skip(count);
+ }
+
+ /// <summary>
+ /// Creates a query by applying the specified take clause.
+ /// </summary>
+ /// <param name="count">The number to take.</param>
+ /// <returns>A query against the table.</returns>
+ public MobileServiceTableQuery<T> Take(int count)
+ {
+ return new MobileServiceTableQuery<T>(this).Take(count);
+ }
+
+ /// <summary>
+ /// Creates a query that will ensure it gets the total count for all
+ /// the records that would have been returned ignoring any take paging/
+ /// limit clause specified by client or server.
+ /// </summary>
+ /// <returns>A query against the table.</returns>
+ public MobileServiceTableQuery<T> IncludeTotalCount()
+ {
+ return new MobileServiceTableQuery<T>(this, true);
+ }
+
+ /// <summary>
+ /// Gets the elements of the table asynchronously.
+ /// </summary>
+ /// <returns>The table element results.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Not nested when used via async pattern.")]
+ public Task<IEnumerable<T>> ToEnumerableAsync()
+ {
+ return this.ReadAsync();
+ }
+
+ /// <summary>
+ /// Gets the elements of the table asynchronously and return the
+ /// results in a new List.
+ /// </summary>
+ /// <returns>The table elements results as a List.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Not nested when used via async pattern.")]
+ public async Task<List<T>> ToListAsync()
+ {
+ return new TotalCountList<T>(await this.ReadAsync());
+ }
+
+ /// <summary>
+ /// Create a new collection view based on the query.
+ /// </summary>
+ /// <returns>The collection view.</returns>
+ public MobileServiceCollectionView<T> ToCollectionView()
+ {
+ return new MobileServiceTableQuery<T>(this).ToCollectionView();
+ }
+ }
+}
89 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Core/MobileServiceTable.Managed.cs
@@ -0,0 +1,89 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Data.Json;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// Provides operations on tables for a Mobile Service.
+ /// </summary>
+ internal partial class MobileServiceTable
+ {
+ /// <summary>
+ /// Gets the name of the results key in an inline count response
+ /// object.
+ /// </summary>
+ protected const string InlineCountResultsKey = "results";
+
+ /// <summary>
+ /// Gets the name of the count key in an inline count response object.
+ /// </summary>
+ protected const string InlineCountCountKey = "count";
+
+ /// <summary>
+ /// Excute a query against a table.
+ /// </summary>
+ /// <param name="query">
+ /// An object defining the query to execute.
+ /// </param>
+ /// <returns>
+ /// A task that will return with results when the query finishes.
+ /// </returns>
+ [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "1#", Justification = "Query is both a verb and noun.")]
+ public Task<IJsonValue> ReadAsync(string query)
+ {
+ return this.SendReadAsync(query);
+ }
+
+ /// <summary>
+ /// Insert a new object into a table.
+ /// </summary>
+ /// <param name="instance">
+ /// The instance to insert into the table.
+ /// </param>
+ /// <returns>
+ /// A task that will complete when the insert finishes.
+ /// </returns>
+ public Task<IJsonValue> InsertAsync(JsonObject instance)
+ {
+ return this.SendInsertAsync(instance);
+ }
+
+ /// <summary>
+ /// Update an object in a given table.
+ /// </summary>
+ /// <param name="instance">
+ /// The instance to update in the table.
+ /// </param>
+ /// <returns>
+ /// A task that will complete when the update finishes.
+ /// </returns>
+ public Task<IJsonValue> UpdateAsync(JsonObject instance)
+ {
+ return this.SendUpdateAsync(instance);
+ }
+
+ /// <summary>
+ /// Delete an object from a given table.
+ /// </summary>
+ /// <param name="instance">
+ /// The instance to delete from the table.
+ /// </param>
+ /// <returns>
+ /// A task that will complete when the delete finishes.
+ /// </returns>
+ public Task DeleteAsync(JsonObject instance)
+ {
+ return this.SendDeleteAsync(instance);
+ }
+ }
+}
209 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Microsoft.Azure.Zumo.Windows.Managed.csproj
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),win8sdk.sln))\tools\Zumo.settings.targets" />
+ <PropertyGroup>
+ <!-- Override Zumo.settings.targets framework version and output path-->
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <StyleCopEnabled>false</StyleCopEnabled>
+ <OutputPath>$(ZumoRootPath)bin\$(Configuration)\Windows 8\Managed\</OutputPath>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{CA8CCA43-81F0-4CE5-855C-70D5D2D462D8}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.WindowsAzure.MobileServices</RootNamespace>
+ <AssemblyName>Microsoft.WindowsAzure.MobileServices.Managed</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>BasicCorrectnessRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <DocumentationFile>..\..\bin\Debug\Windows 8\Managed\Microsoft.WindowsAzure.MobileServices.Managed.XML</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ <DocumentationFile>..\..\bin\Release\Windows 8\Managed\Microsoft.WindowsAzure.MobileServices.Managed.XML</DocumentationFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\Core\IMobileServiceTable.cs">
+ <Link>Core\IMobileServiceTable.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\Core\JsonExtensions.cs">
+ <Link>Core\JsonExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\Core\MobileServiceClient.cs">
+ <Link>Core\MobileServiceClient.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\Core\MobileServiceTable.cs">
+ <Link>Core\MobileServiceTable.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\Core\MobileServiceUser.cs">
+ <Link>Core\MobileServiceUser.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\Core\Resources.cs">
+ <Link>Core\Resources.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\Core\TypeExtensions.cs">
+ <Link>Core\TypeExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\GlobalSuppressions.cs">
+ <Link>GlobalSuppressions.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\ComposedServiceFilter.cs">
+ <Link>ServiceFilter\ComposedServiceFilter.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\IServiceFilter.cs">
+ <Link>ServiceFilter\IServiceFilter.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\IServiceFilterContinuation.cs">
+ <Link>ServiceFilter\IServiceFilterContinuation.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\IServiceFilterRequest.cs">
+ <Link>ServiceFilter\IServiceFilterRequest.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\IServiceFilterResponse.cs">
+ <Link>ServiceFilter\IServiceFilterResponse.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\ServiceFilter.cs">
+ <Link>ServiceFilter\ServiceFilter.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\ServiceFilterRequest.cs">
+ <Link>ServiceFilter\ServiceFilterRequest.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\ServiceFilterResponse.cs">
+ <Link>ServiceFilter\ServiceFilterResponse.cs</Link>
+ </Compile>
+ <Compile Include="..\Microsoft.Azure.Zumo.Windows.WinMD\ServiceFilter\ServiceFilterResponseStatus.cs">
+ <Link>ServiceFilter\ServiceFilterResponseStatus.cs</Link>
+ </Compile>
+ <Compile Include="Core\IMobileServiceTable.Generic.cs" />
+ <Compile Include="Core\IMobileServiceTable.Managed.cs" />
+ <Compile Include="Core\MobileServiceTable.Generic.cs" />
+ <Compile Include="Core\MobileServiceTable.Managed.cs" />
+ <Compile Include="Core\MobileServiceInvalidOperationException.cs" />
+ <Compile Include="Table\CollectionView\VectorChangedEventArgs.cs" />
+ <Compile Include="Table\Query\FilterBuildingExpressionVisitor.cs" />
+ <Compile Include="Table\Query\ITotalCountProvider.cs" />
+ <Compile Include="Table\Query\TotalCountEnumerable.cs" />
+ <Compile Include="Table\Query\TotalCountList.cs" />
+ <Compile Include="Table\Serialization\DataTableAttribute.cs" />
+ <Compile Include="Table\Serialization\ICustomMobileServiceTableSerialization.cs" />
+ <Compile Include="Table\Query\MobileServiceTableQueryDescription.cs" />
+ <Compile Include="Table\Query\PartialEvaulator.cs" />
+ <Compile Include="Table\Query\MobileServiceTableQueryTranslator.cs" />
+ <Compile Include="Table\Query\VisitorHelper.cs" />
+ <Compile Include="Resources.cs" />
+ <Compile Include="Table\Serialization\DataMemberJsonConverterAttribute.cs" />
+ <Compile Include="Table\Serialization\IDataMemberJsonConverter.cs" />
+ <Compile Include="Table\Serialization\SerializableMember.cs" />
+ <Compile Include="Table\Serialization\SerializableType.cs" />
+ <Compile Include="TypeExtensions.cs" />
+ <Compile Include="Table\CollectionView\MobileServiceCollectionView.cs" />
+ <Compile Include="Table\Query\MobileServiceTableQuery.cs" />
+ <Compile Include="Table\Serialization\MobileServiceTableSerializer.cs" />
+ <Compile Include="Core\MobileServiceClient.Managed.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' ">
+ <VisualStudioVersion>11.0</VisualStudioVersion>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject />
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
16 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Microsoft.WindowsAzure.MobileServices.Managed")]
+[assembly: AssemblyDescription("Mobile Services Client Library for Windows 8 Managed Applications")]
+[assembly: CLSCompliant(false)]
+#if SIGNED
+[assembly: InternalsVisibleTo("Microsoft.Azure.Zumo.CSharp.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
+#else
+[assembly: InternalsVisibleTo("Microsoft.Azure.Zumo.CSharp.Test")]
+#endif
144 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Resources.cs
@@ -0,0 +1,144 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// Provides access to localizable resources.
+ /// </summary>
+ internal static partial class Resources
+ {
+ // TODO: Pull these from resources once we figure out how to get
+ // .resw's properly included in the resources.pri for a .winmd
+
+ /// <summary>
+ /// Gets a format string for throwing InvalidOperationExceptions when
+ /// a user provides a [DataMemberJsonConverter(ConverterType =
+ /// typeof(Foo))] that does not implement IDataMemberJsonConverter.
+ /// </summary>
+ public static string SerializableType_GetConverter_DoesNotImplementConverter
+ {
+ get { return "ConverterType '{0}' does not implement the IDataMemberJsonConverter interface."; }
+ }
+
+ /// <summary>
+ /// Gets a format string for throwing ArgumentExceptions when a user
+ /// tries to serialize a type without an "id" property.
+ /// </summary>
+ public static string SerializableType_Ctor_MemberNotFound
+ {
+ get { return "No '{0}' member found on type '{1}'."; }
+ }
+
+ /// <summary>
+ /// Gets a format string for throwing ArgumentExceptions when a user
+ /// tries to deserialize something other than an object.
+ /// </summary>
+ public static string MobileServiceTableSerializer_Deserialize_NeedObject
+ {
+ get { return "Expected a JSON object to deserialize, not '{0}'."; }
+ }
+
+ /// <summary>
+ /// Gets a format string for throwing ArgumentExceptions when a user
+ /// tries to deserialize a value that we can't process.
+ /// </summary>
+ public static string MobileServiceTableSerializer_Deserialize_CannotDeserializeValue
+ {
+ get { return "Cannot deserialize value {0} into '{1}.{2}'."; }
+ }
+
+ /// <summary>
+ /// Gets a format string for throwing SerializationExceptions when a
+ /// user tries to deserialize an object missing required members.
+ /// </summary>
+ public static string MobileServiceTableSerializer_Deserialize_MissingRequired
+ {
+ get { return "Cannot deserialize type '{0}' because the JSON object did not have required member(s) '{1}'."; }
+ }
+
+ /// <summary>
+ /// Gets a format string for throwing ArgumentExceptions when a user
+ /// tries to serialize an unknown type.
+ /// </summary>
+ public static string MobileServiceTableSerializer_Serialize_UnknownType
+ {
+ get { return "Cannot serialize member '{0}' of type '{1}' declared on type '{2}'."; }
+ }
+
+ /// <summary>
+ /// Gets a format string for throwing InvalidOperationExceptions when
+ /// we can't get a single object from a response.
+ /// </summary>
+ public static string MobileServiceTables_GetSingleValueAsync_NotSingleObject
+ {
+ get { return "Could not get object from response {0}."; }
+ }
+
+ /// <summary>
+ /// Gets a format string for throwing InvalidOperationExceptions when
+ /// we can't get an array from a response.
+ /// </summary>
+ public static string MobileServiceTables_GetResponseSequence_ExpectedArray
+ {
+ get { return "Could not get an array from response {0}."; }
+ }
+
+ /// <summary>
+ /// Get a format string for throwing a NotSupportedException when we
+ /// see an unsupported method expression.
+ /// </summary>
+ public static string MobileServiceTableQueryTranslator_ThrowForUnsupportedException_Unsupported
+ {
+ get { return "Expression '{1}' is not a supported '{0}' Mobile Services query expression."; }
+ }
+
+ /// <summary>
+ /// Get a format string for throwing a NotSupportedException when we
+ /// see an unsupported value for OrderBy.
+ /// </summary>
+ public static string MobileServiceTableQueryTranslator_GetOrdering_Unsupported
+ {
+ get { return "'{0}' Mobile Services query expressions must consist of members only, not '{1}'."; }
+ }
+
+ /// <summary>
+ /// Get a format string for throwing a NotSupportedException when we
+ /// see an unsupported value for Skip/Take.
+ /// </summary>
+ public static string MobileServiceTableQueryTranslator_GetCountArgument_Unsupported
+ {
+ get { return "'{0}' Mobile Services query expressions must consist of a single integer, not '{1}'."; }
+ }
+
+ /// <summary>
+ /// Get a format string for throwing a NotSupportedException when we
+ /// see an unsupported operator.
+ /// </summary>
+ public static string FilterBuildingExpressionVisitor_VisitOperator_Unsupported
+ {
+ get { return "The operator '{0}' is not supported in the 'Where' Mobile Services query expression '{1}'."; }
+ }
+
+ /// <summary>
+ /// Get a format string for throwing a NotSupportedException when we
+ /// see an unsupported member.
+ /// </summary>
+ public static string FilterBuildingExpressionVisitor_VisitMember_Unsupported
+ {
+ get { return "The member '{0}' is not supported in the 'Where' Mobile Services query expression '{1}'."; }
+ }
+
+ /// <summary>
+ /// Get a format string for throwing a NotSupportedException when we
+ /// see an unsupported expression.
+ /// </summary>
+ public static string FilterBuildingExpressionVisitor_Visit_Unsupported
+ {
+ get { return "'{0}' is not supported in a 'Where' Mobile Services query expression."; }
+ }
+ }
+}
798 sdk/windows/src/Microsoft.Azure.Zumo.Windows.Managed/Table/CollectionView/MobileServiceCollectionView.cs
@@ -0,0 +1,798 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// ----------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml.Data;
+
+namespace Microsoft.WindowsAzure.MobileServices
+{
+ /// <summary>
+ /// An asynchronous data source that can wrap the results of a Mobile
+ /// Services query in a way that's easily consumed by Xaml collection
+ /// controls like ListView.
+ /// </summary>
+ /// <typeparam name="T">Data source element type.</typeparam>
+ /// <remarks>
+ /// This currently just handles asynchronously loading the data and
+ /// notifying the controls, but we'd eventually like to support paging,
+ /// UI virtualization, and a host of other features.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification = "CollectionView is a more appropriate suffix.")]
+ public sealed class MobileServiceCollectionView<T> :
+ // Note that ICollectionView includes IList<object> which prevents us
+ // from implementing IList<T> as well (since the two could unify for
+ // some types). We've worked around this by explicitly implementing
+ // the IList<object> interface and providing all the IList<T> methods
+ // without actually implementing it. It will make it easy enough to
+ // use as a strongly typed collection, but you'll need to explicitly
+ // cast to IList<object> or IList before passing it into a collection.
+ ICollectionView,
+ System.Collections.IList,
+ INotifyPropertyChanged,
+ INotifyCollectionChanged,
+ ISupportIncrementalLoading
+ {
+ /// <summary>
+ /// The table associated with the query represented by this data
+ /// source.
+ /// </summary>
+ private MobileServiceTable<T> table;
+
+ /// <summary>
+ /// The cached copy of our data that provides a basic implementation
+ /// of our collection interfaces.
+ /// </summary>
+ private List<T> data = null;
+
+ /// <summary>
+ /// The query that when evaluated will populate the data souce with
+ /// data. We'll evaluate the query once per page while data
+ /// virtualizing.
+ /// </summary>
+ private MobileServiceTableQueryDescription query = null;
+
+ /// <summary>
+ /// Initializes a new instance of the MobileServiceCollectionView
+ /// class.
+ /// </summary>
+ /// <param name="table">
+ /// Table associated with the data source's query.
+ /// </param>
+ /// <param name="query">The query the data source represents.</param>
+ internal MobileServiceCollectionView(MobileServiceTable<T> table, MobileServiceTableQueryDescription query)
+ {
+ Debug.Assert(table != null, "table cannot be null!");
+ Debug.Assert(query != null, "query cannot be null!");
+
+ this.table = table;
+ this.query = query;
+
+ // Evaluate the query immediately and start loading the data for it
+ this.data = new List<T>();
+ this.EvaluateQueryAsync();
+ }
+
+ /// <summary>
+ /// Occurs when a property value changes.
+ /// </summary>
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ /// <summary>
+ /// Occurs when the collection changes.
+ /// </summary>
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ /// <summary>
+ /// Occurs then the collection changes.
+ /// </summary>
+ public event VectorChangedEventHandler<object> VectorChanged;
+
+ /// <summary>
+ /// Occurs before the current item is changed.
+ /// </summary>
+ public event CurrentChangingEventHandler CurrentChanging;
+
+ /// <summary>
+ /// Occurs after the current item has been changed.
+ /// </summary>
+ public event EventHandler<object> CurrentChanged;
+
+ /// <summary>
+ /// Gets the number of elements contained in the collection.
+ /// </summary>
+ public int Count
+ {
+ get { return this.data.Count; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the collection is read-only.
+ /// </summary>
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether there are more items that can be
+ /// loaded incrementally.
+ /// </summary>
+ public bool HasMoreItems
+ {
+ // TODO: Implement this once we support paging.
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets the collection groups associated with the collection view.
+ /// </summary>
+ public IObservableVector<object> CollectionGroups
+ {
+ // TODO: Decide if we want to support grouping - or at least return
+ // an empty collection instead of null.
+ get { return null; }
+ }
+
+ /// <summary>
+ /// Gets the position of the current item within the collection view.
+ /// </summary>
+ public int CurrentPosition { get; private set; }
+
+ /// <summary>
+ /// Gets the current item in the collection view.
+ /// </summary>
+ public object CurrentItem
+ {
+ get
+ {
+ return (this.CurrentPosition >= 0 && this.CurrentPosition < this.data.Count) ?
+ (object)this.data[this.CurrentPosition] :
+ null;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current item is before the
+ /// beginning of the collection.
+ /// </summary>
+ public bool IsCurrentBeforeFirst
+ {
+ get { return this.CurrentPosition < 0; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current item is after the end
+ /// of the collection.
+ /// </summary>
+ public bool IsCurrentAfterLast
+ {
+ // TODO: This will of course need to change once we support paging.
+ get { return this.CurrentPosition >= this.Count; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether or not the current item is within
+ /// the bounds of the collection view.
+ /// </summary>
+ private bool IsCurrentInView
+ {
+ get { return !this.IsCurrentBeforeFirst && !this.IsCurrentAfterLast; }
+ }
+
+ #region Collection members
+ /// <summary>
+ /// Gets the number of items in the collection.
+ /// </summary>
+ int System.Collections.ICollection.Count
+ {
+ get { return this.Count; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the collection is synchronized.
+ /// </summary>
+ bool System.Collections.ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets an object used to synchronize the collection.
+ /// </summary>
+ object System.Collections.ICollection.SyncRoot
+ {
+ get { return null; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the list has a fixed size.
+ /// </summary>
+ bool System.Collections.IList.IsFixedSize
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the collection is readonly.
+ /// </summary>
+ bool System.Collections.IList.IsReadOnly
+ {
+ get { return this.IsReadOnly; }
+ }
+ #endregion Collection members
+
+ /// <summary>
+ /// Gets or sets the item at the specified index.
+ /// </summary>
+ /// <param name="index">Index of the item to get or set.</param>
+ /// <returns>The element at the specified index.</returns>
+ public T this[int index]
+ {
+ get { return this.data[index]; }
+ set
+ {
+ T old = this.data[index];
+ this.data[index] = value;
+ this.OnCollectionChanged(
+ new NotifyCollectionChangedEventArgs(
+ NotifyCollectionChangedAction.Replace,
+ value,
+ old,
+ index));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets an element at a given index.
+ /// </summary>
+ /// <param name="index">The index to retrieve.</param>
+ /// <returns>The element at that index.</returns>
+ object System.Collections.IList.this[int index]
+ {
+ get { return this[index]; }
+ set { this[index] = (T)value; }
+ }
+
+ /// <summary>
+ /// Gets or sets an element at a given index.
+ /// </summary>
+ /// <param name="index">The index to retrieve.</param>
+ /// <returns>The element at that index.</returns>
+ object IList<object>.this[int index]
+ {
+ get { return this[index]; }
+ set { this[index] = (T)value; }
+ }
+
+ /// <summary>
+ /// Occurs when a property changes.
+ /// </summary>
+ /// <param name="propertyName">Name of the property.</param>
+ private void OnPropertyChanged([CallerMemberName] string propertyName = "")
+ {
+ PropertyChangedEventHandler handler = this.PropertyChanged;
+ if (handler != null)
+ {
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ #region Data virtualization
+ /// <summary>
+ /// Evaluate the query and repopulate our collection with the results.
+ /// </summary>
+ private async void EvaluateQueryAsync()
+ {
+ // Invoke the query on the server and get our data
+ IEnumerable<T> data = await MobileServiceTable<T>.EvaluateQueryAsync<T>(this.table, this.query);
+
+ // Reset the collection with the new data
+ this.data.Clear();
+ this.data.AddRange(data);
+
+ this.OnCollectionChanged(
+ new NotifyCollectionChangedEventArgs(
+ NotifyCollectionChangedAction.Reset));
+ }
+
+ /// <summary>
+ /// Load more items asynchronously.
+ /// </summary>
+ /// <param name="count">The number of items to load.</param>
+ /// <returns>The result of loading the items.</returns>
+ public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
+ {
+ // TODO: Implement once we support paging
+ throw new NotImplementedException();
+ }
+ #endregion Data virtualization
+
+ #region Currency
+ /// <summary>
+ /// Raise the CurrentChanging event.
+ /// </summary>
+ /// <returns>
+ /// A value indicating whether the change should be cancelled.
+ /// </returns>
+ private bool RaiseCurrentChanging()
+ {
+ bool cancel = false;
+
+ CurrentChangingEventHandler handler = this.CurrentChanging;
+ if (handler != null)
+ {
+ CurrentChangingEventArgs args = new CurrentChangingEventArgs(true);
+ handler(this, args);
+ cancel = args.Cancel;
+ }
+
+ return cancel;
+ }
+
+ /// <summary>
+ /// Raise the CurrentChanged event.
+ /// </summary>
+ private void RaiseCurrentChanged()
+ {
+ EventHandler<object> handler = this.CurrentChanged;
+ if (handler != null)
+ {
+ handler(this, this.CurrentItem);
+ }
+ }
+
+ /// <summary>
+ /// Sets the specified position as the current item in the collection
+ /// view.
+ /// </summary>
+ /// <param name="index">Index of the current item.</param>
+ /// <returns>
+ /// A value indicating whether the current item is within the
+ /// collection view.
+ /// </returns>
+ public bool MoveCurrentToPosition(int index)
+ {
+ if (this.RaiseCurrentChanging())
+ {
+ this.CurrentPosition = index;
+ this.RaiseCurrentChanged();
+ }
+
+ return this.IsCurrentInView;
+ }
+
+ /// <summary>
+ /// Sets the first instance of the specified item in our currentoy
+ /// loaded data as the current item in the collection view.
+ /// </summary>
+ /// <param name="item">The item to search for.</param>
+ /// <returns>
+ /// A value indicating whether the current item is within the
+ /// collection view.
+ /// </returns>
+ public bool MoveCurrentTo(object item)
+ {
+ // Lookup the (first) index of the item in our currently cached
+ // values and move to its position
+ int index = this.data.IndexOf((T)item);
+ return this.MoveCurrentToPosition(index);
+ }
+
+ /// <summary>
+ /// Move the current item to the first item in the collection view.
+ /// </summary>
+ /// <returns>
+ /// A value indicating whether the current item is within the
+ /// collection view.
+ /// </returns>
+ public bool MoveCurrentToFirst()
+ {
+ if (this.RaiseCurrentChanging())
+ {
+ this.CurrentPosition = this.Count > 0 ? 0 : -1;
+ this.RaiseCurrentChanged();
+ }
+
+ return this.IsCurrentInView;
+ }
+
+ /// <summary>
+ /// Move the current item to the last item in the collection view.
+ /// </summary>
+ /// <returns>
+ /// A value indicating whether the current item is within the
+ /// collection view.
+ /// </returns>
+ public bool MoveCurrentToLast()
+ {
+ if (this.RaiseCurrentChanging())
+ {
+ this.CurrentPosition = this.Count > 0 ?
+ this.Count - 1 :
+ 0;
+ this.RaiseCurrentChanged();
+ }
+
+ return this.IsCurrentInView;
+ }
+
+ /// <summary>
+ /// Move the current item to the next item in the collection view.
+ /// </summary>
+ /// <returns>
+ /// A value indicating whether the current item is within the
+ /// collection view.
+ /// </returns>
+ public bool MoveCurrentToNext()
+ {
+ if (this.RaiseCurrentChanging())
+ {
+ if (!this.IsCurrentAfterLast)
+ {
+ this.CurrentPosition++;
+ }
+ this.RaiseCurrentChanged();
+ }
+
+ return this.IsCurrentInView;
+ }
+
+ /// <summary>
+ /// Move the current item to the previous item in the collection view.
+ /// </summary>
+ /// <returns>
+ /// A value indicating whether the current item is within the
+ /// collection view.
+ /// </returns>
+ public bool MoveCurrentToPrevious()
+ {
+ if (this.RaiseCurrentChanging())
+ {
+ if (!this.IsCurrentBeforeFirst)
+ {
+ this.CurrentPosition--;
+ }
+ this.RaiseCurrentChanged();
+ }
+
+ return this.IsCurrentInView;
+ }
+ #endregion Currency
+
+ #region Collection members
+ /// <summary>
+ /// Occurs when the collection changes.
+ /// </summary>
+ /// <param name="args">Collection changed arguments.</param>
+ private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
+ {
+ Debug.Assert(args != null, "args cannot be null.");
+
+ NotifyCollectionChangedEventHandler handler = this.CollectionChanged;
+ if (handler != null)
+ {
+ handler(this, args);
+ }
+
+ // Also raise VectorChanged using the information passed to us via
+ // the CollectionChanged args.
+ VectorChangedEventHandler<object> vectorHandler = this.VectorChanged;
+ if (vectorHandler != null)
+ {
+ CollectionChange change;
+ uint index;
+ switch (args.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ change = CollectionChange.ItemInserted;
+ index = (uint)args.NewStartingIndex;
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ change = CollectionChange.ItemRemoved;
+ index = (uint)args.OldStartingIndex;
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ case NotifyCollectionChangedAction.Replace:
+ change = CollectionChange.ItemChanged;
+ index = (uint)args.NewStartingIndex;
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ default:
+ change = CollectionChange.Reset;
+ index = 0;
+ break;
+ }
+
+ vectorHandler(this, new VectorChangedEventArgs(change, index));
+ }
+ }
+
+ /// <summary>
+ /// Adds an item to the collection.
+ /// </summary>
+ /// <param name="item">The item to add to the collection.</param>
+ public void Add(T item)
+ {
+ this.data.Add(item);
+ this.OnCollectionChanged(
+ new NotifyCollectionChangedEventArgs(
+ NotifyCollectionChangedAction.Add,
+ item,
+ this.data.Count - 1));
+ }
+
+ /// <summary>
+ /// Adds an item to the collection.
+ /// </summary>
+ /// <param name="item">The item to add to the collection.</param>
+ void ICollection<object>.Add(object item)
+ {
+ this.Add((T)item);
+ }
+
+ /// <summary>
+ /// Adds an item the collection.
+ /// </summary>
+ /// <param name="value">Item to add.</param>
+ /// <returns>The position the item was inserted.</returns>
+ int System.Collections.IList.Add(object value)
+ {
+ this.Add((T)value);
+ return this.Count - 1;
+ }
+
+ /// <summary>
+ /// Insert an item into the collection at the specified index.
+ /// </summary>
+ /// <param name="index">The index to insert at.</param>
+ /// <param name="item">The item to insert.</param>
+ public void Insert(int index, T item)
+ {
+ this.data.Insert(index, item);
+ this.OnCollectionChanged(
+ new NotifyCollectionChangedEventArgs(
+ NotifyCollectionChangedAction.Add,
+ item,
+ index));
+ }
+
+ /// <summary>
+ /// Insert an item into the collection at the specified index.
+ /// </summary>
+ /// <param name="index">The index to insert at.</param>
+ /// <param name="item">The item to insert.</param>
+ void IList<object>.Insert(int index, object item)
+ {
+ this.Insert(index, (T)item);
+ }
+
+ /// <summary>
+ /// Insert an item into the collection at the specified index.
+ /// </summary>
+ /// <param name="index">The index to insert at.</param>
+ /// <param name="value">The item to insert.</param>
+ void System.Collections.IList.Insert(int index, object value)
+ {
+ this.Insert(index, (T)value);
+ }
+
+ /// <summary>
+ /// Removes the item at the specified index.
+ /// </summary>
+ /// <param name="index">Index of the item to remove.</param>
+ public void RemoveAt(int index)
+ {
+ T old = this.data[index];
+ this.data.RemoveAt(index);
+
+ this.OnCollectionChanged(
+ new NotifyCollectionChangedEventArgs(
+ NotifyCollectionChangedAction.Remove,
+ old,
+ index));
+ }
+
+ /// <summary>
+ /// Removes the item at the specified index.
+ /// </summary>
+ /// <param name="index">Index of the item to remove.</param>
+ void System.Collections.IList.RemoveAt(int index)
+ {
+ this.RemoveAt(index);
+ }
+
+ /// <summary>
+ /// Removes the first occurence of the specified item from the list.
+ /// </summary>
+ /// <param name="item">The item to remove.</param>
+ /// <returns>True if removed, false otherwise.</returns>
+ public bool Remove(T item)
+ {
+ // Calling _data.Remove directly caused memory corruption when we
+ // raised the notification changed event (likely because the native
+ // INCC event listener was't happy being passed an item that was
+ // no longer in the collection).
+
+ int index = this.data.IndexOf(item);
+ if (index >= 0)
+ {
+ this.data.RemoveAt(index);
+ this.OnCollectionChanged(
+ new NotifyCollectionChangedEventArgs(
+ NotifyCollectionChangedAction.Remove,
+ item,
+ index));
+ return true;
+ }
+