private static bool TestSerializationPolicies(Type type) { var fullSerializerMembers = fsMetaType .Get(new fsConfig(), type) .Properties .Select(p => p._memberInfo) .OrderBy(m => m.MetadataToken) .ToList(); var odinSerializerMembers = FormatterUtilities.GetSerializableMembers(type, SerializationPolicy.instance) .OrderBy(m => m.MetadataToken) .ToList(); var matches = fullSerializerMembers.SequenceEqual(odinSerializerMembers); if (!matches) { Debug.LogWarning($"Serialization Policy mismatch on {type}: \n\nFull Serializer members:\n{fullSerializerMembers.Select(m => m.Name).ToLineSeparatedString()}\n\nOdin Serializer members:\n{odinSerializerMembers.Select(m => m.Name).ToLineSeparatedString()}\n"); } return(matches); }
/// <summary> /// Generates an AOT DLL, using the given parameters. /// </summary> public static void GenerateDLL(string dirPath, string assemblyName, List <Type> supportSerializedTypes, bool generateLinkXml = true) { if (!dirPath.EndsWith("/")) { dirPath += "/"; } var newDllPath = dirPath + assemblyName; var fullDllPath = newDllPath + ".dll"; var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName() { Name = assemblyName }, AssemblyBuilderAccess.Save, dirPath); var module = assembly.DefineDynamicModule(assemblyName); assembly.SetCustomAttribute(new CustomAttributeBuilder(typeof(EmittedAssemblyAttribute).GetConstructor(new Type[0]), new object[0])); // The following is a fix for Unity's crappy Mono runtime that doesn't know how to do this sort // of stuff properly // // We must manually remove the "Default Dynamic Assembly" module that is automatically defined, // otherwise a reference to that non-existent module will be saved into the assembly's IL, and // that will cause a multitude of issues. // // We do this by forcing there to be only one module - the one we just defined, and we set the // manifest module to be that module as well. { var modulesField = assembly.GetType().GetField("modules", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var manifestModuleField = assembly.GetType().GetField("manifest_module", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (modulesField != null) { modulesField.SetValue(assembly, new ModuleBuilder[] { module }); } if (manifestModuleField != null) { manifestModuleField.SetValue(assembly, module); } } var type = module.DefineType(assemblyName + ".PreventCodeStrippingViaReferences", TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.NotPublic); CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(typeof(PreserveAttribute).GetConstructor(Type.EmptyTypes), new object[0]); type.SetCustomAttribute(attributeBuilder); var staticConstructor = type.DefineTypeInitializer(); var il = staticConstructor.GetILGenerator(); HashSet <Type> seenTypes = new HashSet <Type>(); //var endPoint = il.DefineLabel(); //il.Emit(OpCodes.Br, endPoint); foreach (var serializedType in supportSerializedTypes) { if (serializedType == null) { continue; } if (serializedType.IsAbstract || serializedType.IsInterface) { Debug.LogError("Skipping type '" + serializedType.GetNiceFullName() + "'! Type is abstract or an interface."); continue; } if (serializedType.IsGenericType && (serializedType.IsGenericTypeDefinition || !serializedType.IsFullyConstructedGenericType())) { Debug.LogError("Skipping type '" + serializedType.GetNiceFullName() + "'! Type is a generic type definition, or its arguments contain generic parameters; type must be a fully constructed generic type."); continue; } if (seenTypes.Contains(serializedType)) { continue; } seenTypes.Add(serializedType); // Reference serialized type { if (serializedType.IsValueType) { var local = il.DeclareLocal(serializedType); il.Emit(OpCodes.Ldloca, local); il.Emit(OpCodes.Initobj, serializedType); } else { var constructor = serializedType.GetConstructor(Type.EmptyTypes); if (constructor != null) { il.Emit(OpCodes.Newobj, constructor); il.Emit(OpCodes.Pop); } } } // Reference and/or create formatter type if (!FormatterUtilities.IsPrimitiveType(serializedType) && !typeof(UnityEngine.Object).IsAssignableFrom(serializedType)) { var actualFormatter = FormatterLocator.GetFormatter(serializedType, SerializationPolicies.Unity); if (actualFormatter.GetType().IsDefined <EmittedFormatterAttribute>()) { //TODO: Make emitted formatter code compatible with IL2CPP //// Emit an actual AOT formatter into the generated assembly //if (this.emitAOTFormatters) //{ // var emittedFormatter = FormatterEmitter.EmitAOTFormatter(typeEntry.Type, module, SerializationPolicies.Unity); // var emittedFormatterConstructor = emittedFormatter.GetConstructor(Type.EmptyTypes); // il.Emit(OpCodes.Newobj, emittedFormatterConstructor); // il.Emit(OpCodes.Pop); //} } var formatters = FormatterLocator.GetAllCompatiblePredefinedFormatters(serializedType, SerializationPolicies.Unity); foreach (var formatter in formatters) { // Reference the pre-existing formatter var formatterConstructor = formatter.GetType().GetConstructor(Type.EmptyTypes); if (formatterConstructor != null) { il.Emit(OpCodes.Newobj, formatterConstructor); il.Emit(OpCodes.Pop); } } //// Make sure we have a proper reflection formatter variant if all else goes wrong //il.Emit(OpCodes.Newobj, typeof(ReflectionFormatter<>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes)); //il.Emit(OpCodes.Pop); } ConstructorInfo serializerConstructor; // Reference serializer variant if (serializedType.IsEnum) { serializerConstructor = typeof(EnumSerializer <>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes); } else { serializerConstructor = typeof(ComplexTypeSerializer <>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes); } il.Emit(OpCodes.Newobj, serializerConstructor); il.Emit(OpCodes.Pop); } //il.MarkLabel(endPoint); il.Emit(OpCodes.Ret); type.CreateType(); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } if (File.Exists(fullDllPath)) { File.Delete(fullDllPath); } if (File.Exists(fullDllPath + ".meta")) { File.Delete(fullDllPath + ".meta"); } try { AssetDatabase.Refresh(); } catch (Exception) { // Sigh, Unity 5.3.0 } assembly.Save(assemblyName); File.Move(newDllPath, fullDllPath); if (generateLinkXml) { File.WriteAllText(dirPath + "link.xml", @"<linker> <assembly fullname=""" + assemblyName + @""" preserve=""all""/> </linker>"); } try { AssetDatabase.Refresh(); } catch (Exception) { // Sigh, Unity 5.3.0 } var pluginImporter = PluginImporter.GetAtPath(fullDllPath) as PluginImporter; if (pluginImporter != null) { //pluginImporter.ClearSettings(); pluginImporter.SetCompatibleWithEditor(false); pluginImporter.SetCompatibleWithAnyPlatform(true); // Disable for all standalones pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux, false); pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false); pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinuxUniversal, false); // StandaloneOSXUniversal (<= 2017.2) / StandaloneOSX (>= 2017.3) pluginImporter.SetCompatibleWithPlatform((BuildTarget)2, false); if (!UnityVersion.IsVersionOrGreater(2017, 3)) { pluginImporter.SetCompatibleWithPlatform((BuildTarget)4, false); // StandaloneOSXIntel pluginImporter.SetCompatibleWithPlatform((BuildTarget)27, false); // StandaloneOSXIntel64 } pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false); pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false); //pluginImporter.SetCompatibleWithPlatform(BuildTarget.Android, false); pluginImporter.SaveAndReimport(); } AssetDatabase.SaveAssets(); }
/// <summary> /// Generates an AOT DLL, using the given parameters. /// </summary> public static void GenerateDLL(string dirPath, string assemblyName, List <Type> supportSerializedTypes, bool generateLinkXml = true) { #if UNITY_EDITOR && NET_4_6 if (!dirPath.EndsWith("/")) { dirPath += "/"; } var newDllPath = dirPath + assemblyName; var fullDllPath = newDllPath + ".dll"; var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName() { Name = assemblyName }, AssemblyBuilderAccess.Save, dirPath); var module = assembly.DefineDynamicModule(assemblyName); assembly.SetCustomAttribute(new CustomAttributeBuilder(typeof(EmittedAssemblyAttribute).GetConstructor(new Type[0]), new object[0])); // VRChat Edit: Add the UnityAPICompatibilityVersion Attribute for the current version of Unity to skip API Updating. #if UNITY_2019 assembly.SetCustomAttribute(new CustomAttributeBuilder( typeof(UnityAPICompatibilityVersionAttribute).GetConstructor(new[] { typeof(string), typeof(bool) }), new object[] { Application.unityVersion, true }) ); #else assembly.SetCustomAttribute(new CustomAttributeBuilder( typeof(UnityAPICompatibilityVersionAttribute).GetConstructor(new[] { typeof(string) }), new object[] { Application.unityVersion }) ); #endif // The following is a fix for Unity's crappy Mono runtime that doesn't know how to do this sort // of stuff properly // // We must manually remove the "Default Dynamic Assembly" module that is automatically defined, // otherwise a reference to that non-existent module will be saved into the assembly's IL, and // that will cause a multitude of issues. // // We do this by forcing there to be only one module - the one we just defined, and we set the // manifest module to be that module as well. { var modulesField = assembly.GetType().GetField("modules", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var manifestModuleField = assembly.GetType().GetField("manifest_module", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (modulesField != null) { modulesField.SetValue(assembly, new ModuleBuilder[] { module }); } if (manifestModuleField != null) { manifestModuleField.SetValue(assembly, module); } } var type = module.DefineType(assemblyName + ".PreventCodeStrippingViaReferences", TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.NotPublic); CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(typeof(PreserveAttribute).GetConstructor(Type.EmptyTypes), new object[0]); type.SetCustomAttribute(attributeBuilder); var staticConstructor = type.DefineTypeInitializer(); var il = staticConstructor.GetILGenerator(); var falseLocal = il.DeclareLocal(typeof(bool)); il.Emit(OpCodes.Ldc_I4_0); // Load false il.Emit(OpCodes.Stloc, falseLocal); // Set to falseLocal HashSet <Type> seenTypes = new HashSet <Type>(); if (UnityVersion.Major == 2019 && UnityVersion.Minor == 2) { // This here is a hack that fixes Unity's assembly updater triggering faultily in Unity 2019.2 // (and in early 2019.3 alphas/betas, but we're not handling those). When it triggers, it edits // the generated AOT assembly such that it immediately causes Unity to hard crash. Having this // type reference present in the assembly prevents that from happening. (Any concrete type in // the serialization assembly would work, this one is just a random pick.) // // Unity should have fixed this in 2019.3, but said that a backport to 2019.2 is not guaranteed // to occur, though it might. supportSerializedTypes.Add(typeof(DateTimeFormatter)); } //var endPoint = il.DefineLabel(); //il.Emit(OpCodes.Br, endPoint); foreach (var serializedType in supportSerializedTypes) { if (serializedType == null) { continue; } bool isAbstract = serializedType.IsAbstract || serializedType.IsInterface; if (serializedType.IsGenericType && (serializedType.IsGenericTypeDefinition || !serializedType.IsFullyConstructedGenericType())) { Debug.LogError("Skipping type '" + serializedType.GetNiceFullName() + "'! Type is a generic type definition, or its arguments contain generic parameters; type must be a fully constructed generic type."); continue; } if (seenTypes.Contains(serializedType)) { continue; } seenTypes.Add(serializedType); // Reference serialized type { if (serializedType.IsValueType) { var local = il.DeclareLocal(serializedType); il.Emit(OpCodes.Ldloca, local); il.Emit(OpCodes.Initobj, serializedType); } else if (!isAbstract) { var constructor = serializedType.GetConstructor(Type.EmptyTypes); if (constructor != null) { il.Emit(OpCodes.Newobj, constructor); il.Emit(OpCodes.Pop); } } } // Reference and/or create formatter type if (!FormatterUtilities.IsPrimitiveType(serializedType) && !typeof(UnityEngine.Object).IsAssignableFrom(serializedType) && !isAbstract) { var actualFormatter = FormatterLocator.GetFormatter(serializedType, SerializationPolicies.Unity); if (actualFormatter.GetType().IsDefined <EmittedFormatterAttribute>()) { //TODO: Make emitted formatter code compatible with IL2CPP //// Emit an actual AOT formatter into the generated assembly //if (this.emitAOTFormatters) //{ // var emittedFormatter = FormatterEmitter.EmitAOTFormatter(typeEntry.Type, module, SerializationPolicies.Unity); // var emittedFormatterConstructor = emittedFormatter.GetConstructor(Type.EmptyTypes); // il.Emit(OpCodes.Newobj, emittedFormatterConstructor); // il.Emit(OpCodes.Pop); //} } var formatters = FormatterLocator.GetAllCompatiblePredefinedFormatters(serializedType, SerializationPolicies.Unity); foreach (var formatter in formatters) { // Reference the pre-existing formatter var formatterConstructor = formatter.GetType().GetConstructor(Type.EmptyTypes); if (formatterConstructor != null) { il.Emit(OpCodes.Newobj, formatterConstructor); il.Emit(OpCodes.Pop); } } //// Make sure we have a proper reflection formatter variant if all else goes wrong //il.Emit(OpCodes.Newobj, typeof(ReflectionFormatter<>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes)); //il.Emit(OpCodes.Pop); } ConstructorInfo serializerConstructor; // Reference serializer variant if (serializedType.IsValueType) { serializerConstructor = Serializer.Get(serializedType).GetType().GetConstructor(Type.EmptyTypes); il.Emit(OpCodes.Newobj, serializerConstructor); // The following section is a fix for an issue on IL2CPP for PS4, where sometimes bytecode isn't // generated for methods in base types of needed types - FX, Serializer<T>.ReadValueWeak() // may be missing. This only seems to happen in a relevant way for value types. { var endLabel = il.DefineLabel(); // Load a false local value, then jump to the end of this segment of code due to that // false value. This is an attempt to trick any potential code flow analysis made // by IL2CPP that checks whether this segment of code is actually run. // // We don't run the code because if we did, that would actually throw a bunch of // exceptions from invalid calls to ReadValueWeak and WriteValueWeak. il.Emit(OpCodes.Ldloc, falseLocal); il.Emit(OpCodes.Brfalse, endLabel); var baseSerializerType = typeof(Serializer <>).MakeGenericType(serializedType); var readValueWeakMethod = baseSerializerType.GetMethod("ReadValueWeak", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, new Type[] { typeof(IDataReader) }, null); var writeValueWeakMethod = baseSerializerType.GetMethod("WriteValueWeak", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, new Type[] { typeof(string), typeof(object), typeof(IDataWriter) }, null); il.Emit(OpCodes.Dup); // Duplicate serializer instance il.Emit(OpCodes.Ldnull); // Load null argument for IDataReader reader il.Emit(OpCodes.Callvirt, readValueWeakMethod); // Call ReadValueWeak on serializer instance il.Emit(OpCodes.Pop); // Pop result of ReadValueWeak il.Emit(OpCodes.Dup); // Duplicate serializer instance il.Emit(OpCodes.Ldnull); // Load null argument for string name il.Emit(OpCodes.Ldnull); // Load null argument for object value il.Emit(OpCodes.Ldnull); // Load null argument for IDataWriter writer il.Emit(OpCodes.Callvirt, writeValueWeakMethod); // Call WriteValueWeak on serializer instance il.MarkLabel(endLabel); // This is where the code always jumps to, skipping the above } il.Emit(OpCodes.Pop); // Pop the serializer instance } else { serializerConstructor = typeof(ComplexTypeSerializer <>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes); il.Emit(OpCodes.Newobj, serializerConstructor); il.Emit(OpCodes.Pop); } } //il.MarkLabel(endPoint); il.Emit(OpCodes.Ret); type.CreateType(); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } if (File.Exists(fullDllPath)) { File.Delete(fullDllPath); } if (File.Exists(fullDllPath + ".meta")) { File.Delete(fullDllPath + ".meta"); } try { AssetDatabase.Refresh(); } catch (Exception) { // Sigh, Unity 5.3.0 } assembly.Save(assemblyName); File.Move(newDllPath, fullDllPath); if (generateLinkXml) { File.WriteAllText(dirPath + "link.xml", @"<linker> <assembly fullname=""" + assemblyName + @""" preserve=""all""/> </linker>"); } try { AssetDatabase.Refresh(); } catch (Exception) { // Sigh, Unity 5.3.0 } var pluginImporter = PluginImporter.GetAtPath(fullDllPath) as PluginImporter; if (pluginImporter != null) { //pluginImporter.ClearSettings(); pluginImporter.SetCompatibleWithEditor(false); pluginImporter.SetCompatibleWithAnyPlatform(true); // Disable for all standalones pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false); if (!UnityVersion.IsVersionOrGreater(2019, 2)) { pluginImporter.SetCompatibleWithPlatform((BuildTarget)17, false); // StandaloneLinux pluginImporter.SetCompatibleWithPlatform((BuildTarget)25, false); // StandaloneLinuxUniversal } // StandaloneOSXUniversal (<= 2017.2) / StandaloneOSX (>= 2017.3) pluginImporter.SetCompatibleWithPlatform((BuildTarget)2, false); if (!UnityVersion.IsVersionOrGreater(2017, 3)) { pluginImporter.SetCompatibleWithPlatform((BuildTarget)4, false); // StandaloneOSXIntel pluginImporter.SetCompatibleWithPlatform((BuildTarget)27, false); // StandaloneOSXIntel64 } pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false); //pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false); //pluginImporter.SetCompatibleWithPlatform(BuildTarget.Android, false); pluginImporter.SaveAndReimport(); } AssetDatabase.SaveAssets(); #endif }
/// <summary> /// Get the metadata document as per sync specification for $metadata. /// </summary> /// <returns></returns> private XDocument GetMetadataDocument() { // We only have 1 scope for now. //Note: Currently this is read from the service configuration and * is not allowed anymore for the SetEnableScope method. string scopeName = _configuration.ScopeNames[0]; // Get the type list from the TypeToTableGlobalNameMapping key list. List <Type> typeList = _configuration.TypeToTableGlobalNameMapping.Keys.ToList(); var document = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); // Add Schema node // example: // <Edmx Namespace="http://schemas.microsoft.com/ado/2007/06/edmx"> // <DataServices Namespace="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"> // <Schema Namespace="SyncServiceLibUnitTest" // Alias="Self" // xmlns="http://schemas.microsoft.com/ado/2009/08/edm" // xmlns:sync="http://schemas.microsoft.com/sync/2010/03/syncprotocol"> var edmxNode = new XElement(FormatterConstants.EdmxNamespace + "Edmx", new XAttribute("Version", "1.0"), new XAttribute(XNamespace.Xmlns + FormatterConstants.EdmxNsPrefix, FormatterConstants.EdmxNamespace)); var dataservicesNode = new XElement(FormatterConstants.EdmxNamespace + "DataServices", new XAttribute(FormatterConstants.ODataMetadataNamespace + "DataServiceVersion", "2.0"), new XAttribute(XNamespace.Xmlns + FormatterConstants.ODataMetadataNsPrefix, FormatterConstants.ODataMetadataNamespace)); var schemaNode = new XElement("Schema", new XAttribute(FormatterConstants.AtomPubXmlNsPrefix, _baseEdmNamespace), new XAttribute(XNamespace.Xmlns + FormatterConstants.SyncNsPrefix, FormatterConstants.SyncNamespace), new XAttribute("Namespace", _configuration.ServiceTypeNamespace), new XAttribute("Alias", "Self")); // Add entitycontainer node // example: // <EntityContainer Name="scope_name"> var entityContainerNode = new XElement(_baseEdmNamespace + "EntityContainer", new XAttribute("Name", scopeName)); schemaNode.Add(entityContainerNode); // Add each entry as an EntityType node. foreach (var type in typeList) { // Add the type to the entityContainer Node as an EntitySet node // example: // <EntitySet Name="ScheduleItem" EntityType="SyncServiceLibUnitTest.ScheduleItem" /> var entitySetNode = new XElement(_baseEdmNamespace + "EntitySet", new XAttribute("Name", type.Name), new XAttribute("EntityType", type.FullName)); entityContainerNode.Add(entitySetNode); // Create entity type node // example: <EntityType Name="ScheduleItem"> var entityType = new XElement(_baseEdmNamespace + "EntityType", new XAttribute("Name", type.Name)); schemaNode.Add(entityType); // Get the keys from the Key attribute applied on the entity classes. PropertyInfo[] keyList = ReflectionUtility.GetPrimaryKeysPropertyInfoMapping(type); if (keyList.Length > 0) { // create <Key> node var keyNode = new XElement(_baseEdmNamespace + "Key"); foreach (var key in keyList) { // add PropertyRef nodes // example: <PropertyRef Name="ScheduleItemID" /> var propertyRefNode = new XElement(_baseEdmNamespace + "PropertyRef", new XAttribute("Name", key.Name)); keyNode.Add(propertyRefNode); } entityType.Add(keyNode); } PropertyInfo[] entityProperties = ReflectionUtility.GetPropertyInfoMapping(type); foreach (var property in entityProperties) { // Check if the property has a SyncEntityPropertyNullable attribute. // Presence of this attribute indicates that the property is nullable/non-nullable in the underlying data store. // Some data types such as string are nullable in .NET but may or may not be nullable in the data store (such as a // SQL Server table in a database.) bool isNullable = (0 != property.GetCustomAttributes( SyncServiceConstants.SYNC_ENTITY_PROPERTY_NULLABLE_ATTRIBUTE_TYPE, false).ToList().Count); // create Property node // example: // <Property Name="ScheduleItemID" Type="Edm.Guid" Nullable="false" /> var propertyNode = new XElement(_baseEdmNamespace + "Property", new XAttribute("Name", property.Name), new XAttribute("Type", FormatterUtilities.GetEdmType(property.PropertyType)), new XAttribute("Nullable", isNullable)); entityType.Add(propertyNode); } } // Add filter parameter information to the document. if (_configuration.FilterParameters.Count > 0) { // Write the scynscopeparameters node. // example: <sync:SyncScopeParameters> var syncScopeParamsNode = new XElement(FormatterConstants.SyncNamespace + "SyncScopeParameters"); // We only want to add distinct filter parameters. A single parameter may be applied to many tables internally. var distinctFilterParams = new List <string>(); foreach (var filterParameter in _configuration.FilterParameters) { // Continue with the next filter parameter if we already processed the current one. if (distinctFilterParams.Contains(filterParameter.QueryStringKey)) { continue; } distinctFilterParams.Add(filterParameter.QueryStringKey); string edmType = FormatterUtilities.GetEdmType(filterParameter.ValueType); // The 'Name' of the parameter is the query string key configured in the InitializeService method using the // AddFilterParameterConfiguration method. // example: <sync:ScopeParameter Name="userid" Type="Edm.Guid" /> syncScopeParamsNode.Add( new XElement(FormatterConstants.SyncNamespace + "ScopeParameter", new XAttribute("Name", filterParameter.QueryStringKey), new XAttribute("Type", edmType))); } schemaNode.Add(syncScopeParamsNode); } dataservicesNode.Add(schemaNode); edmxNode.Add(dataservicesNode); document.Add(edmxNode); return(document); }
public IList <MemberInfo> SelectMembers(Type type) { return(FormatterUtilities.GetSerializableMembers(type, this.Policy)); }
protected override IEnumerable <MemberInfo> GetMembers(Type type) { return(FormatterUtilities.GetSerializableMembers(type, SerializationPolicy.instance)); }