-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
What's new in .NET 7 Preview 6 [WIP] #7454
Comments
Type ConvertersExposing type converters for the newly added primitive types
|
JSON contract customizationIn certain situations developers serializing or deserializing JSON find that they don't want to or cannot change types because they i.e. come from external library or it would greatly pollute the code but need to make some changes which influence serialization like removing property, changing how numbers get serialized, how object is created etc. They frequently are forced to either write wrappers or custom converters which are not only a hassle but also make serialization slower. JSON contract customization allows user for more control over what and how types get serialized or deserialized. Opting into customizationThere are two basic ways developers can "plug" into the customization, they both end up assigning
JsonSerializerOptions options = new()
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
Modifiers =
{
(JsonTypeInfo jsonTypeInfo) =>
{
// your modifications here, i.e.:
if (jsonTypeInfo.Type == typeof(int))
{
jsonTypeInfo.NumberHandling = JsonNumberHandling.AllowReadingFromString;
}
}
}
}
};
Point point = JsonSerializer.Deserialize<Point>(@"{""X"":""12"",""Y"":""3""}", options);
Console.WriteLine($"({point.X},{point.Y})"); // (12,3)
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}
Customizations
Customizing propertiesProperties are only relevant when class MyClass
{
private string _name = string.Empty;
public string LastName { get; set; }
public string GetName() => _name;
public void SetName(string name)
{
_name = name;
}
} Before this feature existed you'd need to wrap your type hierarchy or create your own custom converter for that type. Now you can simply fix it: JsonSerializerOptions options = new()
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
Modifiers = { ModifyTypeInfo }
}
};
MyClass obj = new()
{
LastName = "Doe"
};
obj.SetName("John");
string serialized = JsonSerializer.Serialize(obj, options); // {"LastName":"Doe","Name":"John"}
static void ModifyTypeInfo(JsonTypeInfo ti)
{
if (ti.Type != typeof(MyClass))
return;
JsonPropertyInfo property = ti.CreateJsonPropertyInfo(typeof(string), "Name");
property.Get = (obj) =>
{
MyClass myClass = (MyClass)obj;
return myClass.GetName();
};
property.Set = (obj, val) =>
{
MyClass myClass = (MyClass)obj;
string value = (string)val;
myClass.SetName(value);
};
ti.Properties.Add(property);
} Conditional serialization of propertiesIn some usage scenarios it's required that some default values don't get serialized. I.e. you don't want Now it's possible to set your own predicate // string property you'd like to customize
JsonPropertyInfo property = ...;
property.ShouldSerialize = (obj, val) =>
{
// in this specific example we don't use parent but it's available if needed
MyClass parentObj = (MyClass)obj;
string value = (string)val;
return value != "N/A";
}; Sample: Ignoring properties with specific name or typevar modifier = new IgnorePropertiesWithNameOrType();
modifier.IgnorePropertyWithType(typeof(SecretHolder));
modifier.IgnorePropertyWithName("IrrelevantDetail");
JsonSerializerOptions options = new()
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
Modifiers = { modifier.ModifyTypeInfo }
}
};
ExampleClass obj = new()
{
Name = "Test",
Secret = new SecretHolder() { Value = "MySecret" },
IrrelevantDetail = 15,
};
string output = JsonSerializer.Serialize(obj, options); // {"Name":"Test"}
class ExampleClass
{
public string Name { get; set; }
public SecretHolder Secret { get; set; }
public int IrrelevantDetail { get; set; }
}
class SecretHolder
{
public string Value { get; set; }
}
class IgnorePropertiesWithNameOrType
{
private List<Type> _ignoredTypes = new List<Type>();
private List<string> _ignoredNames = new List<string>();
public void IgnorePropertyWithType(Type type)
{
_ignoredTypes.Add(type);
}
public void IgnorePropertyWithName(string name)
{
_ignoredNames.Add(name);
}
public void ModifyTypeInfo(JsonTypeInfo ti)
{
JsonPropertyInfo[] props = ti.Properties.Where((pi) => !_ignoredTypes.Contains(pi.PropertyType) && !_ignoredNames.Contains(pi.Name)).ToArray();
ti.Properties.Clear();
foreach (var pi in props)
{
ti.Properties.Add(pi);
}
}
} |
System.Formats.Tar API updatesIn Preview 4, the In Preview 6, some changes were made to cover a few special cases: Global Extended Attributes specialized classThe initial design was assuming that only PAX TAR archives could contain a single Global Extended Attributes (GEA) entry in the first position, but it was discovered that TAR archives can contain multiple GEA entries, which can affect all subsequent entries until encountering a new GEA entry or the end of the archive. It was also discovered that GEA entries should not be expected only in archives containing PAX entries exclusively: they can show up in archives that intermix entries of different formats. So a new class was added to describe a GEA entry: + public sealed partial class PaxGlobalExtendedAttributesTarEntry : PosixTarEntry
+ {
+ public PaxGlobalExtendedAttributesTarEntry(IEnumerable<KeyValuePair<string, string>> globalExtendedAttributes) { }
+ public IReadOnlyDictionary<string, string> GlobalExtendedAttributes { get { throw null; } }
+ } Entry format, not archive formatSince it was also discovered that entries of different formats can be intermixed in a single TAR archive, the -public enum TarFormat
+public enum TarEntryFormat
{
...
} And a new property was added to public abstract partial class TarEntry
{
...
+ public TarEntryFormat Format { get { throw null; } }
...
} Writing and reading changesThe Since GEA entries are now being described with their own specialized class, and multiple entries of this type can be found in a single archive, the dictionary property from the public sealed partial class TarReader : IDisposable
{
...
- public TarFormat Format { get { throw null; } }
- public IReadOnlyDictionary<string, string>? GlobalExtendedAttributes { get { throw null; } }
...
} The addition of the specialized GEA class also affected
public sealed partial class TarWriter : IDisposable
{
...
- public TarWriter(Stream archiveStream, IEnumerable<KeyValuePair<string, string>>? globalExtendedAttributes = null, bool leaveOpen = false) { }
+ public TarWriter(Stream archiveStream, bool leaveOpen = false) { }
- public TarWriter(Stream archiveStream, TarFormat archiveFormat, bool leaveOpen = false) { }
+ public TarWriter(Stream archiveStream, TarEntryFormat format = TarEntryFormat.Pax, bool leaveOpen = false) { }
public void WriteEntry(string fileName, string? entryName) { }
...
} |
CodeGenCommunity PRs (Many thanks to JIT community contributors!)
Dynamic PGO
For now only delegates bound to instance methods are supported. We expect that support for static methods will come in early previews for .NET 8. (note to editors: the screenshot is taken from the link above, please convert to appropriate code blocks/tables in the final blog post)
Arm64
Loop Optimizations
General Optimizations
|
.NET 7 GA is available. Closing these pre-release issues. |
What's new in .NET 7 Preview 6
This issue is for teams to highlight work for the community that will release .NET 7 Preview 6
To add content, use a new conversation entry. The entry should include the team name and feature title as the first line as shown in the template below.
Preview 1: #7106
Preview 2: #7107
Preview 3: #7108
Preview 4: #7378
Preview 5: #7441
Preview 6: #7454
Preview 7: #7455
The text was updated successfully, but these errors were encountered: