diff --git a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll
index 38bc03d9f9..02d9981c0f 100644
--- a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll
+++ b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:52f819550e98d126a685c556595cb25a66bfc7cd97352fa5d127b4a759b52fdb
-size 724992
+oid sha256:f5307f2607fe9e761088e06baccdcb5ece8739b25418a6b19421004d872c343d
+size 713728
diff --git a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll.hash b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll.hash
index 5533fa4ba9..f4a8390aaa 100644
--- a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll.hash
+++ b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.dll.hash
@@ -1 +1 @@
-52F819550E98D126A685C556595CB25A66BFC7CD97352FA5D127B4A759B52FDB
\ No newline at end of file
+F5307F2607FE9E761088E06BACCDCB5ECE8739B25418A6B19421004D872C343D
\ No newline at end of file
diff --git a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.pdb b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.pdb
new file mode 100644
index 0000000000..64fbd87e8f
--- /dev/null
+++ b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.Packed.pdb
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:68184c5e9ef77e2275e9e8e5f44fb61228b1f7bc8bae9adf461f18d7a10f734a
+size 304640
diff --git a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.dll b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.dll
index 3037adc46a..6d1592834c 100644
--- a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.dll
+++ b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f0b8df74ce667e960698b4dbc8d7a61b2cda58c897befa42cf8943e1577b0e4d
-size 170496
+oid sha256:9f49d4387554f62bc004132b83981db7361dca126d1785470d33aa6a7def835a
+size 159744
diff --git a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.pdb b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.pdb
index 51f595e506..1d231ddcbc 100644
--- a/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.pdb
+++ b/deps/AssemblyProcessor/net6.0/Stride.Core.AssemblyProcessor.pdb
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:312b5beecf5fbed6e51e9cf3202586035bf14fa0d4d5017c095ce0a0a5a09960
-size 89456
+oid sha256:f01d69f07a88527792dafe98e67f2129b477a5af868972bf4d7726d74d44590c
+size 441856
diff --git a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll
index de7cd2f13c..4fdf03c1db 100644
--- a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll
+++ b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e17ab0cb8bc5f55ca985c21612e1da0af77ec6ea6cdd6faf9f76252b0217d226
-size 720896
+oid sha256:f47741092523ec3bf4c9c1b87bec8e1faecc919e1f8319ce64a696f876e186cb
+size 710144
diff --git a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll.hash b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll.hash
index 2b5cb8d208..570a817d79 100644
--- a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll.hash
+++ b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.dll.hash
@@ -1 +1 @@
-E17AB0CB8BC5F55CA985C21612E1DA0AF77EC6EA6CDD6FAF9F76252B0217D226
\ No newline at end of file
+F47741092523EC3BF4C9C1B87BEC8E1FAECC919E1F8319CE64A696F876E186CB
\ No newline at end of file
diff --git a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.pdb b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.pdb
index 9c95aedc33..8937565118 100644
--- a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.pdb
+++ b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.Packed.pdb
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:813198b4a220539954fb7e19f109ba8f8bcbfbcdbad5139d93b02d74f0a99162
-size 302592
+oid sha256:d717d03c4691b4773958d1aa2cbe91d467d6f6765ba081044ed059f8bcda1e5e
+size 304640
diff --git a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.dll b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.dll
index 334a387986..7e1fdce484 100644
--- a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.dll
+++ b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:65f2e1d02ba26e7a7817d94821bdc07a382afe77c9f6a3350a036f46efffb84e
-size 169472
+oid sha256:94be07b9174da333cc863cff8ba50ff484280b28dee0b657b9a9dc0877355860
+size 158720
diff --git a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.pdb b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.pdb
index 3536f2a1ea..25f862638f 100644
--- a/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.pdb
+++ b/deps/AssemblyProcessor/netstandard2.0/Stride.Core.AssemblyProcessor.pdb
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6e5c0460d7f76555500ab34a5f2c2301d1233de50f6b70dc82c907dc0c8a0e70
-size 87032
+oid sha256:6aebc1244c93dd5afee900815020971fbaa96ac7ef17b82325adc7303e4271f6
+size 441856
diff --git a/sources/assets/Stride.Core.Assets.Tests/TestSerializing.TestMyAssetObject.cs b/sources/assets/Stride.Core.Assets.Tests/TestSerializing.TestMyAssetObject.cs
index 1a547731c0..b240a502c4 100644
--- a/sources/assets/Stride.Core.Assets.Tests/TestSerializing.TestMyAssetObject.cs
+++ b/sources/assets/Stride.Core.Assets.Tests/TestSerializing.TestMyAssetObject.cs
@@ -28,7 +28,7 @@ public MyAsset()
// TODO: Re-enable non-pure collections here once we support them for serialization!
//MapItems2 = new MyDictionary();
MapItems3 = new MyDictionaryPure();
- CustomObjectWithProtectedSet = new CustomObject { Name = "customObject" };
+ CustomObjectWithInternalSet = new CustomObject { Name = "customObject" };
}
[DataMember(0)]
@@ -65,7 +65,8 @@ public MyAsset()
public MyDictionaryPure MapItems3 { get; set; }
- public object CustomObjectWithProtectedSet { get; protected set; }
+ [DataMember]
+ public CustomObject CustomObjectWithInternalSet { get; internal set; }
}
[DataContract("CustomObject")]
diff --git a/sources/assets/Stride.Core.Assets.Tests/data/TestSerializing/TestSerializing_TestMyAssetObject_Reference.sdobj b/sources/assets/Stride.Core.Assets.Tests/data/TestSerializing/TestSerializing_TestMyAssetObject_Reference.sdobj
index 3f61d7e27c..704551dd3a 100644
--- a/sources/assets/Stride.Core.Assets.Tests/data/TestSerializing/TestSerializing_TestMyAssetObject_Reference.sdobj
+++ b/sources/assets/Stride.Core.Assets.Tests/data/TestSerializing/TestSerializing_TestMyAssetObject_Reference.sdobj
@@ -27,5 +27,5 @@ MapItems3:
11000000110000001100000011000000~key2: 2
12000000120000001200000012000000~key3: 3
13000000130000001300000013000000~key4: 3
-CustomObjectWithProtectedSet:
+CustomObjectWithInternalSet:
Name: customObject
diff --git a/sources/assets/Stride.Core.Assets/AssetItem.cs b/sources/assets/Stride.Core.Assets/AssetItem.cs
index 768187da88..f349db022c 100644
--- a/sources/assets/Stride.Core.Assets/AssetItem.cs
+++ b/sources/assets/Stride.Core.Assets/AssetItem.cs
@@ -59,6 +59,7 @@ internal AssetItem([NotNull] UFile location, [NotNull] Asset asset, Package pack
///
/// The location.
[NotNull]
+ [DataMember]
public UFile Location { get => location; internal set => location = value ?? throw new ArgumentNullException(nameof(value)); }
///
@@ -84,6 +85,7 @@ internal AssetItem([NotNull] UFile location, [NotNull] Asset asset, Package pack
/// Gets the package where this asset is stored.
///
/// The package.
+ [DataMember]
public Package Package { get; internal set; }
///
@@ -187,6 +189,7 @@ public UFile FullPath
///
/// The asset.
[NotNull]
+ [DataMember]
public Asset Asset { get => asset; internal set => asset = value ?? throw new ArgumentNullException(nameof(value)); }
///
@@ -197,6 +200,7 @@ public UFile FullPath
/// By default, contains the last modified time of the asset from the disk. If IsDirty is also updated from false to true
/// , this time will get current time of modification.
///
+ [DataMember]
public DateTime ModifiedTime { get; internal set; }
private long version;
@@ -204,6 +208,7 @@ public UFile FullPath
///
/// Gets the asset version incremental counter, increased everytime the asset is edited.
///
+ [DataMember]
public long Version { get => Interlocked.Read(ref version); internal set => Interlocked.Exchange(ref version, value); }
///
diff --git a/sources/assets/Stride.Core.Assets/AssetReference.cs b/sources/assets/Stride.Core.Assets/AssetReference.cs
index d9dba6e6aa..ab08fac29c 100644
--- a/sources/assets/Stride.Core.Assets/AssetReference.cs
+++ b/sources/assets/Stride.Core.Assets/AssetReference.cs
@@ -33,14 +33,14 @@ public AssetReference(AssetId id, UFile location)
///
/// The unique identifier of the reference asset..
[DataMember(10)]
- public AssetId Id { get; }
+ public AssetId Id { get; init; }
///
/// Gets or sets the location of the asset.
///
/// The location.
[DataMember(20)]
- public string Location { get; }
+ public string Location { get; init; }
public bool Equals(AssetReference other)
{
diff --git a/sources/assets/Stride.Core.Assets/BasePart.cs b/sources/assets/Stride.Core.Assets/BasePart.cs
index b88c3dd51e..3996eadf25 100644
--- a/sources/assets/Stride.Core.Assets/BasePart.cs
+++ b/sources/assets/Stride.Core.Assets/BasePart.cs
@@ -72,10 +72,10 @@ public BasePart([NotNull] AssetReference basePartAsset, Guid basePartId, Guid in
public AssetReference BasePartAsset { get; set; }
[DataMember(20)]
- public Guid BasePartId { get; }
+ public Guid BasePartId { get; init; }
[DataMember(30)]
- public Guid InstanceId { get; }
+ public Guid InstanceId { get; init; }
[CanBeNull]
public IIdentifiable ResolvePart(PackageSession session)
diff --git a/sources/assets/Stride.Core.Assets/Bundle.cs b/sources/assets/Stride.Core.Assets/Bundle.cs
index f049026f4c..b457902de7 100644
--- a/sources/assets/Stride.Core.Assets/Bundle.cs
+++ b/sources/assets/Stride.Core.Assets/Bundle.cs
@@ -14,15 +14,6 @@ namespace Stride.Core.Assets
[DebuggerDisplay("Bundle [{Name}] Selectors[{Selectors.Count}] Dependencies[{Dependencies.Count}]")]
public sealed class Bundle
{
- ///
- /// Initializes a new instance of the class.
- ///
- public Bundle()
- {
- Selectors = new List();
- Dependencies = new List();
- }
-
///
/// Gets or sets the name of this bundle.
///
@@ -33,13 +24,13 @@ public Bundle()
/// Gets the selectors used by this bundle.
///
/// The selectors.
- public List Selectors { get; private set; }
+ public List Selectors { get; } = new List();
///
/// Gets the bundle dependencies.
///
/// The dependencies.
- public List Dependencies { get; private set; }
+ public List Dependencies { get; } = new List();
///
/// Gets the output group (used in conjonction with to control where file will be put).
diff --git a/sources/assets/Stride.Core.Assets/Selectors/TagSelector.cs b/sources/assets/Stride.Core.Assets/Selectors/TagSelector.cs
index ac2d4c0c90..385d963389 100644
--- a/sources/assets/Stride.Core.Assets/Selectors/TagSelector.cs
+++ b/sources/assets/Stride.Core.Assets/Selectors/TagSelector.cs
@@ -13,19 +13,11 @@ namespace Stride.Core.Assets.Selectors
[DataContract("TagSelector")]
public class TagSelector : AssetSelector
{
- ///
- /// Initializes a new instance of the class.
- ///
- public TagSelector()
- {
- Tags = new TagCollection();
- }
-
///
/// Gets the tags that will be used to select an asset.
///
/// The tags.
- public TagCollection Tags { get; private set; }
+ public TagCollection Tags { get; } = new TagCollection();
public override IEnumerable Select(PackageSession packageSession, IContentIndexMap contentIndexMap)
{
diff --git a/sources/assets/Stride.Core.Assets/SolutionPlatform.cs b/sources/assets/Stride.Core.Assets/SolutionPlatform.cs
index 41b67705ee..87d4504444 100644
--- a/sources/assets/Stride.Core.Assets/SolutionPlatform.cs
+++ b/sources/assets/Stride.Core.Assets/SolutionPlatform.cs
@@ -16,21 +16,12 @@ namespace Stride.Core.Assets
[DataContract("SolutionPlatform")]
public class SolutionPlatform : SolutionPlatformPart
{
- ///
- /// Initializes a new instance of the class.
- ///
- public SolutionPlatform()
- {
- PlatformsPart = new SolutionPlatformPartCollection();
- DefineConstants = new List();
- }
-
///
/// Gets the alternative names that will appear in the .sln file equivalent to this platform.
///
/// The alternative names.
[DataMember(20)]
- public SolutionPlatformPartCollection PlatformsPart { get; private set; }
+ public SolutionPlatformPartCollection PlatformsPart { get; } = new SolutionPlatformPartCollection();
///
/// Gets or sets the type of the platform.
@@ -58,7 +49,7 @@ public SolutionPlatform()
///
/// The define constants.
[DataMember(40)]
- public List DefineConstants { get; private set; }
+ public List DefineConstants { get; } = new List();
///
/// Gets or sets a value indicating whether this is available on this machine.
@@ -274,16 +265,15 @@ public class SolutionConfiguration
///
public SolutionConfiguration(string name)
{
- if (name == null) throw new ArgumentNullException("name");
+ if (name == null) throw new ArgumentNullException(nameof(name));
Name = name;
- Properties = new List();
}
///
/// Gets or sets the configuration name (e.g. Debug, Release)
///
/// The name.
- public string Name { get; private set; }
+ public string Name { get; init; }
///
/// Gets or sets a value indicating whether this instance is a debug configuration.
@@ -295,6 +285,6 @@ public SolutionConfiguration(string name)
/// Gets the additional msbuild properties for a specific configuration (Debug or Release)
///
/// The msbuild configuration properties.
- public List Properties { get; private set; }
+ public List Properties { get; } = new List();
}
}
diff --git a/sources/assets/Stride.Core.Assets/Yaml/YamlAssetPath.cs b/sources/assets/Stride.Core.Assets/Yaml/YamlAssetPath.cs
index 736ffb24b5..8969f7d6f9 100644
--- a/sources/assets/Stride.Core.Assets/Yaml/YamlAssetPath.cs
+++ b/sources/assets/Stride.Core.Assets/Yaml/YamlAssetPath.cs
@@ -127,6 +127,7 @@ public YamlAssetPath([NotNull] IEnumerable elements)
///
/// The elements constituting this path.
///
+ [DataMember]
public IReadOnlyList Elements => elements;
///
diff --git a/sources/core/Stride.Core.AssemblyProcessor/ComplexSerializerRegistry.cs b/sources/core/Stride.Core.AssemblyProcessor/ComplexSerializerRegistry.cs
index 99f0baf0bf..834a54b83e 100644
--- a/sources/core/Stride.Core.AssemblyProcessor/ComplexSerializerRegistry.cs
+++ b/sources/core/Stride.Core.AssemblyProcessor/ComplexSerializerRegistry.cs
@@ -10,7 +10,6 @@
using System.Runtime.CompilerServices;
using System.Text;
using Mono.Cecil;
-using Stride.Core;
namespace Stride.Core.AssemblyProcessor
{
@@ -282,25 +281,33 @@ public static IEnumerable GetSerializableItems(TypeDefinition
var fields = new List();
var properties = new List();
- var fieldEnum = type.Fields.Where(x => (x.IsPublic || (x.IsAssembly && x.CustomAttributes.Any(a => a.AttributeType.FullName == "Stride.Core.DataMemberAttribute"))) && !x.IsStatic && !ignoredMembers.Contains(x));
+ foreach (var field in type.Fields)
+ {
+ if (field.IsStatic)
+ continue;
- // If there is a explicit or sequential layout, sort by offset
- if (type.IsSequentialLayout || type.IsExplicitLayout)
- fieldEnum = fieldEnum.OrderBy(x => x.Offset);
+ if (ignoredMembers.Contains(field))
+ continue;
- foreach (var field in fieldEnum)
- {
- fields.Add(field);
+ if (field.IsPublic || (field.IsAssembly && field.CustomAttributes.Any(a => a.AttributeType.FullName == "Stride.Core.DataMemberAttribute")))
+ fields.Add(field);
}
+ // If there is a explicit or sequential layout, sort by offset
+ if (type.IsSequentialLayout || type.IsExplicitLayout)
+ fields.Sort((x,y) => x.Offset.CompareTo(y.Offset));
+
foreach (var property in type.Properties)
{
+ if (IsAccessibleThroughAccessModifiers(property) == false)
+ continue;
+
// Need a non-static public get method
- if (property.GetMethod == null || !property.GetMethod.IsPublic || property.GetMethod.IsStatic)
+ if (property.GetMethod.IsStatic)
continue;
- // If it's a struct (!IsValueType), we need a public set method as well
- if (property.PropertyType.IsValueType && (property.SetMethod == null || !(property.SetMethod.IsAssembly || property.SetMethod.IsPublic)))
+ // If it's a struct (!IsValueType), we need a set method as well
+ if (property.PropertyType.IsValueType && property.SetMethod == null)
continue;
// Only take virtual properties (override ones will be handled by parent serializers)
@@ -382,6 +389,27 @@ public static IEnumerable GetSerializableItems(TypeDefinition
}
}
+ static bool IsAccessibleThroughAccessModifiers(PropertyDefinition property)
+ {
+ var get = property.GetMethod;
+ var set = property.SetMethod;
+
+ if (get == null)
+ return false;
+
+ bool forced = property.CustomAttributes.Any(a => a.AttributeType.FullName == "Stride.Core.DataMemberAttribute");
+
+ if (forced && (get.IsPublic || get.IsAssembly))
+ return true;
+
+ // By default, allow access for get-only auto-property, i.e.: { get; } but not { get => }
+ // as the later may create side effects, and without a setter, we can't 'set' as a fallback for those exceptional cases.
+ if (get.IsPublic)
+ return set?.IsPublic == true || set == null && property.DeclaringType.Fields.Any(x => x.Name == $"<{property.Name}>k__BackingField");
+
+ return false;
+ }
+
internal static bool IsMemberIgnored(ICollection customAttributes, ComplexTypeSerializerFlags flags, DataMemberMode dataMemberMode)
{
// Check for DataMemberIgnore
diff --git a/sources/core/Stride.Core.Design/Settings/SettingsFile.cs b/sources/core/Stride.Core.Design/Settings/SettingsFile.cs
index a0946fcb1e..803d245dae 100644
--- a/sources/core/Stride.Core.Design/Settings/SettingsFile.cs
+++ b/sources/core/Stride.Core.Design/Settings/SettingsFile.cs
@@ -23,6 +23,6 @@ public SettingsFile(SettingsProfile profile)
/// Gets the settings profile to serialize.
///
[DataMemberCustomSerializer]
- public SettingsProfile Settings { get; private set; }
+ public SettingsProfile Settings { get; init; }
}
}
diff --git a/sources/core/Stride.Core.Reflection/MemberDescriptors/FieldDescriptor.cs b/sources/core/Stride.Core.Reflection/MemberDescriptors/FieldDescriptor.cs
index 90a85e6917..1d313b900e 100644
--- a/sources/core/Stride.Core.Reflection/MemberDescriptors/FieldDescriptor.cs
+++ b/sources/core/Stride.Core.Reflection/MemberDescriptors/FieldDescriptor.cs
@@ -30,7 +30,7 @@ public FieldDescriptor(ITypeDescriptor typeDescriptor, FieldInfo fieldInfo, Stri
public override bool IsPublic => FieldInfo.IsPublic;
- public override bool HasSet => true;
+ public override bool HasSet => !FieldInfo.IsInitOnly;
public override object Get(object thisObject)
{
diff --git a/sources/core/Stride.Core.Reflection/MemberDescriptors/PropertyDescriptor.cs b/sources/core/Stride.Core.Reflection/MemberDescriptors/PropertyDescriptor.cs
index a60fd6e517..061fe581e2 100644
--- a/sources/core/Stride.Core.Reflection/MemberDescriptors/PropertyDescriptor.cs
+++ b/sources/core/Stride.Core.Reflection/MemberDescriptors/PropertyDescriptor.cs
@@ -21,11 +21,9 @@ public PropertyDescriptor(ITypeDescriptor typeDescriptor, PropertyInfo propertyI
PropertyInfo = propertyInfo;
- getMethod = propertyInfo.GetGetMethod(false) ?? propertyInfo.GetGetMethod(true);
- if (propertyInfo.CanWrite && propertyInfo.GetSetMethod(!IsPublic) != null)
- {
- setMethod = propertyInfo.GetSetMethod(!IsPublic);
- }
+ getMethod = propertyInfo.GetMethod;
+ setMethod = propertyInfo.SetMethod;
+
TypeDescriptor = typeDescriptor;
}
diff --git a/sources/core/Stride.Core.Reflection/TypeDescriptors/ObjectDescriptor.cs b/sources/core/Stride.Core.Reflection/TypeDescriptors/ObjectDescriptor.cs
index 65bcab1003..6ff5dc7c9b 100644
--- a/sources/core/Stride.Core.Reflection/TypeDescriptors/ObjectDescriptor.cs
+++ b/sources/core/Stride.Core.Reflection/TypeDescriptors/ObjectDescriptor.cs
@@ -213,11 +213,12 @@ protected virtual List PrepareMembers()
}
// TODO: we might want an option to disable non-public.
- if (Category == DescriptorCategory.Object || Category == DescriptorCategory.NotSupportedObject)
+ if (Category is DescriptorCategory.Object or DescriptorCategory.NotSupportedObject)
bindingFlags |= BindingFlags.NonPublic;
var memberList = (from propertyInfo in Type.GetProperties(bindingFlags)
- where propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0 && IsMemberToVisit(propertyInfo)
+ where Type.IsAnonymous() || IsAccessibleThroughAccessModifiers(propertyInfo)
+ where propertyInfo.GetIndexParameters().Length == 0 && IsMemberToVisit(propertyInfo)
select new PropertyDescriptor(factory.Find(propertyInfo.PropertyType), propertyInfo, NamingConvention.Comparer)
into member
where PrepareMember(member, metadataClassMemberInfos?.FirstOrDefault(x => x.MemberInfo.Name == member.OriginalName && x.MemberType == member.Type).MemberInfo)
@@ -225,7 +226,8 @@ where PrepareMember(member, metadataClassMemberInfos?.FirstOrDefault(x => x.Memb
// Add all public fields
memberList.AddRange(from fieldInfo in Type.GetFields(bindingFlags)
- where fieldInfo.IsPublic && IsMemberToVisit(fieldInfo)
+ where (fieldInfo.IsPublic || (fieldInfo.IsAssembly && fieldInfo.GetCustomAttribute() != null))
+ where IsMemberToVisit(fieldInfo)
select new FieldDescriptor(factory.Find(fieldInfo.FieldType), fieldInfo, NamingConvention.Comparer)
into member
where PrepareMember(member, metadataClassMemberInfos?.FirstOrDefault(x => x.MemberInfo.Name == member.OriginalName && x.MemberType == member.Type).MemberInfo)
@@ -237,6 +239,33 @@ where PrepareMember(member, metadataClassMemberInfos?.FirstOrDefault(x => x.Memb
return memberList;
}
+ static bool IsAccessibleThroughAccessModifiers(PropertyInfo property)
+ {
+ var get = property.GetMethod;
+ var set = property.SetMethod;
+
+ if (get == null)
+ return false;
+
+ bool forced = property.GetCustomAttribute() is not null;
+
+ if (forced && (get.IsPublic || get.IsAssembly))
+ return true;
+
+ // By default, allow access for get-only auto-property, i.e.: { get; } but not { get => }
+ // as the later may create side effects, and without a setter, we can't 'set' as a fallback for those exceptional cases.
+ if (get.IsPublic)
+ return set?.IsPublic == true || set == null && TryGetBackingField(property, out _);
+
+ return false;
+ }
+
+ static bool TryGetBackingField(PropertyInfo property, out FieldInfo backingField)
+ {
+ backingField = property.DeclaringType.GetField($"<{property.Name}>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
+ return backingField != null;
+ }
+
protected virtual bool PrepareMember(MemberDescriptorBase member, MemberInfo metadataClassMemberInfo)
{
var memberType = member.Type;
@@ -253,8 +282,7 @@ protected virtual bool PrepareMember(MemberDescriptorBase member, MemberInfo met
}
// Gets the style
- var styleAttribute = attributes.FirstOrDefault(x => x is DataStyleAttribute) as DataStyleAttribute;
- if (styleAttribute != null)
+ if (attributes.FirstOrDefault(x => x is DataStyleAttribute) is DataStyleAttribute styleAttribute)
{
member.Style = styleAttribute.Style;
member.ScalarStyle = styleAttribute.ScalarStyle;
@@ -265,14 +293,12 @@ protected virtual bool PrepareMember(MemberDescriptorBase member, MemberInfo met
if (memberAttribute != null)
{
((IMemberDescriptor)member).Mask = memberAttribute.Mask;
+ member.Mode = memberAttribute.Mode;
if (!member.HasSet)
{
- if (memberAttribute.Mode == DataMemberMode.Assign ||
- (memberType.IsValueType && member.Mode == DataMemberMode.Content))
- throw new ArgumentException($"{memberType.FullName} {member.OriginalName} is not writeable by {memberAttribute.Mode.ToString()}.");
+ if (memberAttribute.Mode == DataMemberMode.Assign || memberType.IsValueType || memberType == typeof(string))
+ member.Mode = DataMemberMode.Never;
}
-
- member.Mode = memberAttribute.Mode;
member.Order = memberAttribute.Order;
}
@@ -292,16 +318,14 @@ protected virtual bool PrepareMember(MemberDescriptorBase member, MemberInfo met
DefaultValueAttribute defaultValueAttribute = null;
foreach (var attribute in attributes)
{
- var valueAttribute = attribute as DefaultValueAttribute;
- if (valueAttribute != null)
+ if (attribute is DefaultValueAttribute valueAttribute)
{
// If we've already found one, don't overwrite it
defaultValueAttribute = defaultValueAttribute ?? valueAttribute;
continue;
}
- var yamlRemap = attribute as DataAliasAttribute;
- if (yamlRemap != null)
+ if (attribute is DataAliasAttribute yamlRemap)
{
if (member.AlternativeNames == null)
{
@@ -414,12 +438,7 @@ protected bool IsMemberToVisit(MemberInfo memberInfo)
}
}
-
- // Member is not displayed if there is a YamlIgnore attribute on it
- if (AttributeRegistry.GetAttribute(memberInfo) != null)
- return false;
-
- return true;
+ return AttributeRegistry.GetAttribute(memberInfo) is null;
}
}
}
diff --git a/sources/core/Stride.Core.Yaml.Tests/DescriptorTests.cs b/sources/core/Stride.Core.Yaml.Tests/DescriptorTests.cs
index 898f5d68bd..f807c03d2d 100644
--- a/sources/core/Stride.Core.Yaml.Tests/DescriptorTests.cs
+++ b/sources/core/Stride.Core.Yaml.Tests/DescriptorTests.cs
@@ -77,7 +77,7 @@ public TestObject()
public ICollection Collection { get; set; }
- public ICollection CollectionReadOnly { get; private set; }
+ public ICollection CollectionReadOnly { get; }
[DataMemberIgnore]
public string DontSerialize { get; set; }
diff --git a/sources/core/Stride.Core.Yaml.Tests/Serialization/SerializationTests2.cs b/sources/core/Stride.Core.Yaml.Tests/Serialization/SerializationTests2.cs
index 9b343677bc..1bf345acd7 100644
--- a/sources/core/Stride.Core.Yaml.Tests/Serialization/SerializationTests2.cs
+++ b/sources/core/Stride.Core.Yaml.Tests/Serialization/SerializationTests2.cs
@@ -221,7 +221,7 @@ public MyObject()
public int[] Array { get; set; }
- public int[] ArrayContent { get; private set; }
+ public int[] ArrayContent { get; }
}
[Fact]
@@ -576,7 +576,7 @@ public MyCustomClassWithSpecialMembers()
/// value of the list stored in this instance instead of
/// creating a new List<T>l instance.
///
- public List StringListByContent { get; private set; }
+ public List StringListByContent { get; }
///
/// Gets or sets the basic map.
@@ -595,7 +595,7 @@ public MyCustomClassWithSpecialMembers()
/// Idem as for but for dictionary.
///
/// The content of the string mapby.
- public Dictionary StringMapbyContent { get; private set; }
+ public Dictionary StringMapbyContent { get; }
///
/// For this property, the deserializer is using the actual
@@ -603,7 +603,7 @@ public MyCustomClassWithSpecialMembers()
/// creating a new List<T>l instance.
///
/// The content of the list by.
- public IList ListByContent { get; private set; }
+ public List ListByContent { get; }
}
///
@@ -1506,21 +1506,6 @@ public class ObjectWithMask
internal int Int3 { get; set; }
}
- [Fact]
- public void TestImplicitMemberType()
- {
- var settings = new SerializerSettings() {LimitPrimitiveFlowSequence = 0};
-
- var text = @"!ClassWithImplicitMemberType
-Test:
- String: test
-";
-
- settings.RegisterTagMapping("ClassWithImplicitMemberType", typeof(ClassWithImplicitMemberType));
- settings.RegisterTagMapping("ClassWithImplicitMemberTypeInner", typeof(ClassWithImplicitMemberTypeInner));
- SerialRoundTrip(settings, text);
- }
-
[Fact]
public void TestNonImplicitMemberType()
{
@@ -1567,7 +1552,8 @@ public ClassWithImplicitMemberType()
Test = new ClassWithImplicitMemberTypeInner {String = "test"};
}
- public object Test { get; protected set; }
+ [DataMember]
+ public object Test { get; init; }
}
public class ClassWithNonImplicitMemberType
diff --git a/sources/core/Stride.Core/DataMemberMode.cs b/sources/core/Stride.Core/DataMemberMode.cs
index a95e26c81b..272df06038 100644
--- a/sources/core/Stride.Core/DataMemberMode.cs
+++ b/sources/core/Stride.Core/DataMemberMode.cs
@@ -20,15 +20,15 @@ public enum DataMemberMode
Assign,
///
- /// Only valid for a property / field that has a class or struct type.
- /// When restored, instead of recreating the whole class or struct,
+ /// Only valid for a property / field that return a class, no strings, primitives or value types.
+ /// When restored, instead of recreating the whole class,
/// the members are independently restored. When the property / field
/// is not writeable this is the default.
///
Content,
///
- /// Only valid for a property / field that has an array type of a
+ /// Only valid for a property / field that has an array type of
/// some value type. The content of the array is stored in a binary
/// format encoded in base64 style.
///
diff --git a/sources/core/Stride.Core/PropertyKey.cs b/sources/core/Stride.Core/PropertyKey.cs
index 4cd9f9a393..b5fa7a0620 100644
--- a/sources/core/Stride.Core/PropertyKey.cs
+++ b/sources/core/Stride.Core/PropertyKey.cs
@@ -19,6 +19,7 @@ namespace Stride.Core
[DebuggerDisplay("{" + nameof(Name) + "}")]
public abstract class PropertyKey : IComparable
{
+ protected string name;
private DefaultValueMetadata defaultValueMetadata;
///
@@ -42,7 +43,7 @@ protected PropertyKey([NotNull] string name, Type propertyType, Type ownerType,
///
/// Gets the name of this key.
///
- public string Name { get; protected set; }
+ public string Name { get => name; init => name = value; }
///
/// Gets the default value metadata.
diff --git a/sources/core/Stride.Core/Settings/AppSettings.cs b/sources/core/Stride.Core/Settings/AppSettings.cs
index 1ab62c21b6..9a03bbded8 100644
--- a/sources/core/Stride.Core/Settings/AppSettings.cs
+++ b/sources/core/Stride.Core/Settings/AppSettings.cs
@@ -13,8 +13,7 @@ public sealed class AppSettings : IEnumerable