diff --git a/Esiur/Data/NullableAttribute.cs b/Esiur/Data/NullableAttribute.cs index 3bba156..d369000 100644 --- a/Esiur/Data/NullableAttribute.cs +++ b/Esiur/Data/NullableAttribute.cs @@ -1,28 +1,23 @@ namespace System.Runtime.CompilerServices { - [AttributeUsage( - AttributeTargets.Class | - AttributeTargets.Event | - AttributeTargets.Field | - AttributeTargets.GenericParameter | - AttributeTargets.Parameter | - AttributeTargets.Property | - AttributeTargets.ReturnValue, - AllowMultiple = false, - Inherited = false)] + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)] public sealed class NullableAttribute : Attribute { - public readonly byte[] Flags; - //public readonly byte Flag; + /// Flags specifying metadata related to nullable reference types. + public readonly byte[] NullableFlags; - public NullableAttribute(byte flag) + /// Initializes the attribute. + /// The flags value. + public NullableAttribute(byte value) { - //Flag = flag; - Flags = new byte[] { flag }; + NullableFlags = new[] { value }; } - public NullableAttribute(byte[] flags) + + /// Initializes the attribute. + /// The flags value. + public NullableAttribute(byte[] value) { - Flags = flags; + NullableFlags = value; } } } diff --git a/Esiur/Data/NullableContextAttribute.cs b/Esiur/Data/NullableContextAttribute.cs index 2a6b51c..2bfd8e6 100644 --- a/Esiur/Data/NullableContextAttribute.cs +++ b/Esiur/Data/NullableContextAttribute.cs @@ -1,19 +1,16 @@ namespace System.Runtime.CompilerServices { - [System.AttributeUsage( - AttributeTargets.Class | - AttributeTargets.Delegate | - AttributeTargets.Interface | - AttributeTargets.Method | - AttributeTargets.Struct, - AllowMultiple = false, - Inherited = false)] + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] public sealed class NullableContextAttribute : Attribute { + /// Flag specifying metadata related to nullable reference types. public readonly byte Flag; - public NullableContextAttribute(byte flag) + + /// Initializes the attribute. + /// The flag value. + public NullableContextAttribute(byte value) { - Flag = flag; + Flag = value; } } } diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj index b3dbf05..8e24a92 100644 --- a/Esiur/Esiur.csproj +++ b/Esiur/Esiur.csproj @@ -5,7 +5,7 @@ Ahmed Kh. Zamil http://www.esiur.com true - 2.4.8 + 2.4.9 https://github.com/esiur/esiur-dotnet Ahmed Kh. Zamil @@ -56,14 +56,14 @@ - - + + - - + + diff --git a/Esiur/Resource/Template/EventTemplate.cs b/Esiur/Resource/Template/EventTemplate.cs index 15ce70e..2199611 100644 --- a/Esiur/Resource/Template/EventTemplate.cs +++ b/Esiur/Resource/Template/EventTemplate.cs @@ -83,31 +83,36 @@ public class EventTemplate : MemberTemplate var annotationAttr = ei.GetCustomAttribute(true); var listenableAttr = ei.GetCustomAttribute(true); - evtType.Nullable = new NullabilityInfoContext().Create(ei).ReadState is NullabilityState.Nullable; + //evtType.Nullable = new NullabilityInfoContext().Create(ei).ReadState is NullabilityState.Nullable; - //var nullableAttr = ei.GetCustomAttribute(true); - //var nullableContextAttr = ei.GetCustomAttribute(true); + var nullableAttr = ei.GetCustomAttributes().FirstOrDefault(x => x.GetType().Name == "System.Runtime.CompilerServices.NullableAttribute");// .GetCustomAttribute(true); + var nullableContextAttr = ei.GetCustomAttributes().FirstOrDefault(x => x.GetType().Name == "System.Runtime.CompilerServices.NullableContextAttribute");// ei.GetCustomAttribute(true); + + + var nullableAttrFlags = (nullableAttr?.GetType().GetField("NullableFlags").GetValue(nullableAttr) as byte[] ?? new byte[0]).ToList(); + var nullableContextAttrFlag = (byte)(nullableContextAttr?.GetType().GetField("Flag").GetValue(nullableContextAttr) ?? (byte)0); //var flags = nullableAttr?.Flags?.ToList() ?? new List(); + //var flags = ((byte[])nullableAttr?.NullableFlags ?? new byte[0]).ToList(); - //// skip the eventHandler class - //if (flags.Count > 1) - // flags = flags.Skip(1).ToList(); + // skip the eventHandler class + if (nullableAttrFlags.Count > 1) + nullableAttrFlags = nullableAttrFlags.Skip(1).ToList(); - //if (nullableContextAttr?.Flag == 2) - //{ - // if (flags.Count == 1) - // evtType.SetNotNull(flags.FirstOrDefault()); - // else - // evtType.SetNotNull(flags); - //} - //else - //{ - // if (flags.Count == 1) - // evtType.SetNull(flags.FirstOrDefault()); - // else - // evtType.SetNull(flags); - //} + if (nullableContextAttrFlag == 2) + { + if (nullableAttrFlags.Count == 1) + evtType.SetNotNull(nullableAttrFlags.FirstOrDefault()); + else + evtType.SetNotNull(nullableAttrFlags); + } + else + { + if (nullableAttrFlags.Count == 1) + evtType.SetNull(nullableAttrFlags.FirstOrDefault()); + else + evtType.SetNull(nullableAttrFlags); + } var et = new EventTemplate(typeTemplate, index, customName ?? ei.Name, ei.DeclaringType != type, evtType); et.EventInfo = ei; diff --git a/Esiur/Resource/Template/FunctionTemplate.cs b/Esiur/Resource/Template/FunctionTemplate.cs index cd05102..0ead1ec 100644 --- a/Esiur/Resource/Template/FunctionTemplate.cs +++ b/Esiur/Resource/Template/FunctionTemplate.cs @@ -91,41 +91,56 @@ public class FunctionTemplate : MemberTemplate var annotationAttr = mi.GetCustomAttribute(true); - var nullabilityInfoContext = new NullabilityInfoContext(); - - rtType.Nullable = nullabilityInfoContext.Create(mi.ReturnParameter).WriteState is NullabilityState.Nullable; + //var nullabilityInfoContext = new NullabilityInfoContext(); + //rtType.Nullable = nullabilityInfoContext.Create(mi.ReturnParameter).WriteState is NullabilityState.Nullable; - //var nullableAttr = mi.GetCustomAttribute(true); - //var nullableContextAttr = mi.GetCustomAttribute(true); + var nullableAttr = mi.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute"); + var nullableContextAttr = mi.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttribute"); - //var flags = nullableAttr?.Flags?.ToList() ?? new List(); + var nullableAttrFlags = (nullableAttr?.GetType().GetField("NullableFlags").GetValue(nullableAttr) as byte[] ?? new byte[0]).ToList(); + var nullableContextAttrFlag = (byte)(nullableContextAttr?.GetType().GetField("Flag").GetValue(nullableContextAttr) ?? (byte)0); + + //var flags = ((byte[])nullableAttr?.NullableFlags ?? new byte[0]).ToList(); //var rtNullableAttr = mi.ReturnTypeCustomAttributes.GetCustomAttributes(typeof(NullableAttribute), true).FirstOrDefault() as NullableAttribute; - //var rtNullableContextAttr = mi.ReturnTypeCustomAttributes + var rtNullableAttr = mi.ReturnTypeCustomAttributes.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute"); + + + + // var rtNullableContextAttr = mi.ReturnTypeCustomAttributes // .GetCustomAttributes(typeof(NullableContextAttribute), true) - // .FirstOrDefault() as NullableContextAttribute + // .FirstOrDefault() as NullableContextAttribute // ?? nullableContextAttr; + + var rtNullableContextAttr = mi.ReturnTypeCustomAttributes + .GetCustomAttributes(true).FirstOrDefault(x=>x.GetType().Name == "NullableContextAttribute") + ?? nullableContextAttr; + + var rtNullableAttrFlags = (rtNullableAttr?.GetType().GetField("NullableFlags").GetValue(rtNullableAttr) as byte[] ?? new byte[0]).ToList(); + var rtNullableContextAttrFlag = (byte)(rtNullableContextAttr?.GetType().GetField("Flag").GetValue(rtNullableContextAttr) ?? (byte)0); + //var rtFlags = rtNullableAttr?.Flags?.ToList() ?? new List(); + //var rtFlags = ((byte[])rtNullableAttr?.NullableFlags ?? new byte[0]).ToList(); - //if (rtFlags.Count > 0 && genericRtType == typeof(AsyncReply<>)) - // rtFlags.RemoveAt(0); + if (rtNullableAttrFlags.Count > 0 && genericRtType == typeof(AsyncReply<>)) + rtNullableAttrFlags.RemoveAt(0); - //if (rtNullableContextAttr?.Flag == 2) - //{ - // if (rtFlags.Count == 1) - // rtType.SetNotNull(rtFlags.FirstOrDefault()); - // else - // rtType.SetNotNull(rtFlags); - //} - //else - //{ - // if (rtFlags.Count == 1) - // rtType.SetNull(rtFlags.FirstOrDefault()); - // else - // rtType.SetNull(rtFlags); - //} + if (rtNullableContextAttrFlag == 2) + { + if (rtNullableAttrFlags.Count == 1) + rtType.SetNotNull(rtNullableAttrFlags.FirstOrDefault()); + else + rtType.SetNotNull(rtNullableAttrFlags); + } + else + { + if (rtNullableAttrFlags.Count == 1) + rtType.SetNull(rtNullableAttrFlags.FirstOrDefault()); + else + rtType.SetNull(rtNullableAttrFlags); + } var args = mi.GetParameters(); @@ -142,28 +157,34 @@ public class FunctionTemplate : MemberTemplate if (argType == null) throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`"); - argType.Nullable = nullabilityInfoContext.Create(x).WriteState is NullabilityState.Nullable; + //argType.Nullable = nullabilityInfoContext.Create(x).WriteState is NullabilityState.Nullable; //var argNullableAttr = x.GetCustomAttribute(true); //var argNullableContextAttr = x.GetCustomAttribute(true) ?? nullableContextAttr; + var argNullableAttr = x.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute"); + var argNullableContextAttr = x.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttr"); + //var argFlags = argNullableAttr?.Flags?.ToList() ?? new List(); + //var argFlags = ((byte[])argNullableAttr?.NullableFlags ?? new byte[0]).ToList(); + var argNullableAttrFlags = (argNullableAttr?.GetType().GetField("NullableFlags").GetValue(argNullableAttr) as byte[] ?? new byte[0]).ToList(); + var argNullableContextAttrFlag = (byte)(argNullableAttr?.GetType().GetField("Flag").GetValue(argNullableAttr) ?? (byte)0); - //if (argNullableContextAttr?.Flag == 2) - //{ - // if (argFlags.Count == 1) - // argType.SetNotNull(argFlags.FirstOrDefault()); - // else - // argType.SetNotNull(argFlags); - //} - //else - //{ - // if (rtFlags.Count == 1) - // argType.SetNull(argFlags.FirstOrDefault()); - // else - // argType.SetNull(argFlags); - //} + if (argNullableContextAttrFlag == 2) + { + if (argNullableAttrFlags.Count == 1) + argType.SetNotNull(argNullableAttrFlags.FirstOrDefault()); + else + argType.SetNotNull(argNullableAttrFlags); + } + else + { + if (argNullableAttrFlags.Count == 1) + argType.SetNull(argNullableAttrFlags.FirstOrDefault()); + else + argType.SetNull(argNullableAttrFlags); + } return new ArgumentTemplate() { diff --git a/Esiur/Resource/Template/PropertyTemplate.cs b/Esiur/Resource/Template/PropertyTemplate.cs index 028744b..a34081a 100644 --- a/Esiur/Resource/Template/PropertyTemplate.cs +++ b/Esiur/Resource/Template/PropertyTemplate.cs @@ -150,8 +150,6 @@ public class PropertyTemplate : MemberTemplate this.ValueType = valueType; } - - public static PropertyTemplate MakePropertyTemplate(Type type, PropertyInfo pi, byte index = 0, string customName = null, TypeTemplate typeTemplate = null) { var genericPropType = pi.PropertyType.IsGenericType ? pi.PropertyType.GetGenericTypeDefinition() : null; @@ -166,32 +164,36 @@ public class PropertyTemplate : MemberTemplate var annotationAttr = pi.GetCustomAttribute(true); var storageAttr = pi.GetCustomAttribute(true); - var nullabilityContext = new NullabilityInfoContext(); - propType.Nullable = nullabilityContext.Create(pi).ReadState is NullabilityState.Nullable; + //var nullabilityContext = new NullabilityInfoContext(); + //propType.Nullable = nullabilityContext.Create(pi).ReadState is NullabilityState.Nullable; + + var nullableAttr = pi.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute"); + var nullableContextAttr = pi.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttribute"); + + var nullableAttrFlags = (nullableAttr?.GetType().GetField("NullableFlags").GetValue(nullableAttr) as byte[] ?? new byte[0]).ToList(); + var nullableContextAttrFlag = (byte)(nullableContextAttr?.GetType().GetField("Flag").GetValue(nullableContextAttr) ?? (byte)0); - // var nullableContextAttr = pi.GetCustomAttribute(true); - // var nullableAttr = pi.GetCustomAttribute(true); + //var nullableAttr = pi.GetCustomAttribute(true); + //var flags = ((byte[]) nullableAttr?.NullableFlags ?? new byte[0]).ToList(); - // var flags = nullableAttr?.Flags?.ToList() ?? new List(); + if (nullableAttrFlags.Count > 0 && genericPropType == typeof(DistributedPropertyContext<>)) + nullableAttrFlags.RemoveAt(0); - // if (flags.Count > 0 && genericPropType == typeof(DistributedPropertyContext<>)) - // flags.RemoveAt(0); - - // if (nullableContextAttr?.Flag == 2) - // { - // if (flags.Count == 1) - // propType.SetNotNull(flags.FirstOrDefault()); - // else - // propType.SetNotNull(flags); - // } - // else - // { - // if (flags.Count == 1) - // propType.SetNull(flags.FirstOrDefault()); - // else - // propType.SetNull(flags); - // } + if (nullableContextAttrFlag == 2) + { + if (nullableAttrFlags.Count == 1) + propType.SetNotNull(nullableAttrFlags.FirstOrDefault()); + else + propType.SetNotNull(nullableAttrFlags); + } + else + { + if (nullableAttrFlags.Count == 1) + propType.SetNull(nullableAttrFlags.FirstOrDefault()); + else + propType.SetNull(nullableAttrFlags); + } var pt = new PropertyTemplate(typeTemplate, index, customName ?? pi.Name, pi.DeclaringType != type, propType); diff --git a/Test/MyService.cs b/Test/MyService.cs index 80e5e78..c043891 100644 --- a/Test/MyService.cs +++ b/Test/MyService.cs @@ -120,6 +120,7 @@ public partial class MyService [Export] public MyRecord Record => new MyRecord() { Id = 33, Name = "Test", Score = 99.33 }; + [Export] public MyRecord? RecordNullable => new MyRecord() { Id = 33, Name = "Test Nullable", Score = 99.33 }; [Export] public List IntList => new List() { 1, 2, 3, 4, 5 };