-
Notifications
You must be signed in to change notification settings - Fork 5k
[API Proposal]: DataContract API's to enable external Schema Import/Export package #72242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Are these APIs expected to be used outside the BCL? If not, perhaps they should be put in an Another idea I thought is to make these APIs public on the |
namespace System.Runtime.Serialization.Schema
{
public sealed class DataContractSet
{
[RequiresUnreferencedCode("")]
public DataContractSet(DataContractSet dataContractSet);
public DataContractSet(
ISerializationSurrogateProvider? dataContractSurrogate,
ICollection<Type>? referencedTypes,
ICollection<Type>? referencedCollectionTypes);
public Dictionary<XmlQualifiedName, DataContract> Contracts { get; }
public Dictionary<XmlQualifiedName, DataContract>? KnownTypesForObject { get; }
public Dictionary<DataContract, object> ProcessedContracts { get; }
public Hashtable SurrogateData { get; }
[RequiresUnreferencedCode("")]
public void Add(Type type);
[RequiresUnreferencedCode("")]
public void ExportSchemaSet(XmlSchemaSet schemaSet);
[RequiresUnreferencedCode("")]
public DataContract GetDataContract(Type type);
[RequiresUnreferencedCode("")]
public DataContract? GetDataContract(XmlQualifiedName key);
[RequiresUnreferencedCode("")]
public Type? GetReferencedType(
XmlQualifiedName stableName,
DataContract dataContract,
out DataContract? referencedContract,
out object[]? genericParameters,
bool? supportGenericTypes = null);
[RequiresUnreferencedCode("")]
public void ImportSchemaSet(
XmlSchemaSet schemaSet,
ICollection<XmlQualifiedName>? typeNames,
bool importXmlDataType);
[RequiresUnreferencedCode("")]
public IList<XmlQualifiedName> ImportSchemaSet(
XmlSchemaSet schemaSet,
ICollection<XmlSchemaElement> elements,
bool importXmlDataType);
}
public abstract class DataContract
{
public virtual bool IsBuiltInDataContract { get; }
[DynamicallyAccessedMembers(*)]
public virtual Type UnderlyingType { get; }
public virtual XmlQualifiedName XmlName { get; }
public virtual Type OriginalUnderlyingType { get; }
public virtual List<DataMember>? Members { get; }
public virtual Dictionary<XmlQualifiedName, DataContract>? KnownDataContracts { get; set; }
public virtual bool IsValueType { get; }
public virtual bool IsReference { get; }
public virtual bool IsISerializable { get; }
public virtual XmlDictionaryString? TopLevelElementName { get; }
public virtual XmlDictionaryString? TopLevelElementNamespace { get; }
public virtual DataContract? BaseContract { get; }
public virtual string? ContractType { get; }
public static string EncodeLocalName(string localName);
[RequiresUnreferencedCode("")]
public static DataContract? GetBuiltInDataContract(string name, string ns);
[RequiresUnreferencedCode("")]
public static DataContract GetDataContract(Type type);
[RequiresUnreferencedCode("")]
public static XmlQualifiedName GetXmlName(Type type);
[RequiresUnreferencedCode("")]
public static Type GetSurrogateType(ISerializationSurrogateProvider surrogateProvider, Type type);
[RequiresUnreferencedCode("")]
public static bool IsTypeSerializable(Type type);
[RequiresUnreferencedCode("")]
public virtual XmlQualifiedName GetArrayTypeName(bool isNullable);
public virtual bool IsDictionaryLike(out string? keyName, out string? valueName, out string? itemName);
}
public sealed class XmlDataContract : DataContract
{
public bool HasRoot { get; }
public bool IsAnonymous { get; }
public bool IsTopLevelElementNullable { get; }
public bool IsTypeDefinedOnImport { get; set; }
public bool IsValueType { get; set; }
public XmlSchemaType? XsdType { get; }
}
public sealed class DataMember
{
public bool EmitDefaultValue { get; }
public bool IsNullable { get; }
public bool IsRequired { get; }
public DataContract MemberTypeContract { get; }
public string Name { get; }
public long Order { get; }
}
}
namespace System.Runtime.Serialization
{
public interface ISerializationSurrogateProvider2 : ISerializationSurrogateProvider
{
object? GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType);
object? GetCustomDataToExport(Type runtimeType, Type dataContractType);
void GetKnownCustomDataTypes(Collection<Type> customDataTypes);
Type? GetReferencedTypeOnImport(string typeName, string typeNamespace, object? customData);
}
}
namespace System.Runtime.Serialization.Json
{
public partial class DataContractJsonSerializer
{
public System.Runtime.Serialization.ISerializationSurrogateProvider? GetSerializationSurrogateProvider();
public void SetSerializationSurrogateProvider(System.Runtime.Serialization.ISerializationSurrogateProvider? provider);
}
} |
After moving the schema exporter stuff from the other review back into the runtime assembly, there are 5 API's above that no longer need to be exposed. Additionally, I believe we discussed moving the utility method namespace System.Runtime.Serialization.DataContracts
{
public sealed class DataContractSet
{
[RequiresUnreferencedCode("")]
public void Add(Type type);
[RequiresUnreferencedCode("")]
public void ExportSchemaSet(XmlSchemaSet schemaSet);
}
public abstract class DataContract
{
// Removing setter only. Getter still exists on public API.
public virtual Dictionary<XmlQualifiedName, DataContract>? KnownDataContracts { set; }
public static string EncodeLocalName(string localName);
[RequiresUnreferencedCode("")]
public static DataContract GetDataContract(Type type);
[RequiresUnreferencedCode("")]
public static Type GetSurrogateType(ISerializationSurrogateProvider surrogateProvider, Type type);
[RequiresUnreferencedCode("")]
public static bool IsTypeSerializable(Type type);
}
} With regards to the various collection types in the API signature:
Also, to be consistent with .Net 4.8 and the new Finally, instead of stashing these newly exposed types in a new 'System.Runtime.Serialization.Schema' namespace, we settled on 'System.Runtime.Serialization.DataContracts' since they are all classes that implement/support the DataContract model. (All the internal sub-classes of DataContract have moved into this namespace as well, not that that is relevant to the public API discussion.) |
@bartonjs - As referenced above, we were able to remove several of the API's originally listed when we brought the schema exporter back into the runtime package. Additionally, @mconnew and I discussed the use of namespace System.Runtime.Serialization.DataContracts
{
public abstract class DataContract
{
// This previously approved API
//public virtual List<DataMember>? Members { get; }
// Now looks like this:
public virtual ReadOnlyCollection<DataMember> DataMembers { get; }
}
} Do we see any problems with this tightening up? |
Implemented in #71752 |
Background and motivation
We're trying to bring DCS and friends back to par with .Net 4.8 in this release. One of the capabilities of the DCS library in .Net 4.8 is to generate XSD schemas or import XSD schemas into usable code. This functionality is used to support WCF and svcutil. The code that handles schema importing however, had a dependency on System.CodeDom. After some extended discussion around the goals and motivations, we decided to take a two-pronged approach here. The existing DCS assembly in the runtime will be recieving updates to align with 4.8 and to support this schema work under the covers... but the top-level functionality (and public surface area) of the schema support will live in a separate package in dotnet/runtime that is not part of the runtime. (Like the System.CodeDom package it depends on.) See the PR #71752 and other half of the API review #72243.
Schema support in 4.8 relied heavily on DCS internals, which wasn't a problem since those and CodeDom were all there. To do this schema work in an external package though, we need to expose some API points from the System.Runtime.Serialization namespace. I've tried to keep these to a minimum, and at a somewhat logical and abstract level so they don't look too contrived or out of place for a public API. But the intent here is to support what we need for XSD schema processing - not to open up the internals of DCS anymore than we need to.
Classes being exposed by this proposal are as follows:
Additionally, a new interface is being added, and the DataContractJsonSerializer is receiving an extension method that the Xml DCS already had for supplying surrogate providers.
API Proposal
API Usage
I'm not sure where to begin on this one. The schema support package needs to reason about and manage DataContracts, and these API's allow it to do so without exposing all the internals.
Alternative Designs
No response
Risks
These are largely methods that existed as-is or very close to how they are in 4.8. But they were internal before, not public. I do believe they reasonably support what we need. I expect there will be quite a bit of discussion though as it is a large and publicly un-proven surface we are opening up.
The text was updated successfully, but these errors were encountered: