2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-05-06 11:32:59 +00:00
esiur-dotnet/Esiur/Resource/Template/PropertyTemplate.cs
2024-11-10 14:49:53 +03:00

223 lines
6.1 KiB
C#

using Esiur.Data;
using Esiur.Net.IIP;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Esiur.Resource.Template;
public class PropertyTemplate : MemberTemplate
{
public enum PropertyPermission : byte
{
Read = 1,
Write,
ReadWrite
}
public PropertyInfo PropertyInfo
{
get;
set;
}
public RepresentationType ValueType { get; set; }
/*
public bool Serilize
{
get;set;
}
*/
//bool ReadOnly;
//IIPTypes::DataType ReturnType;
public PropertyPermission Permission
{
get;
set;
}
public bool IsNullable { get; set; }
public bool Recordable
{
get;
set;
}
/*
public PropertyType Mode
{
get;
set;
}*/
public string ReadAnnotation
{
get;
set;
}
public string WriteAnnotation
{
get;
set;
}
/*
public bool Storable
{
get;
set;
}*/
public override byte[] Compose()
{
var name = base.Compose();
var pv = ((byte)(Permission) << 1) | (Recordable ? 1 : 0);
if (Inherited)
pv |= 0x80;
if (WriteAnnotation != null && ReadAnnotation != null)
{
var rexp = DC.ToBytes(ReadAnnotation);
var wexp = DC.ToBytes(WriteAnnotation);
return new BinaryList()
.AddUInt8((byte)(0x38 | pv))
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ValueType.Compose())
.AddInt32(wexp.Length)
.AddUInt8Array(wexp)
.AddInt32(rexp.Length)
.AddUInt8Array(rexp)
.ToArray();
}
else if (WriteAnnotation != null)
{
var wexp = DC.ToBytes(WriteAnnotation);
return new BinaryList()
.AddUInt8((byte)(0x30 | pv))
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ValueType.Compose())
.AddInt32(wexp.Length)
.AddUInt8Array(wexp)
.ToArray();
}
else if (ReadAnnotation != null)
{
var rexp = DC.ToBytes(ReadAnnotation);
return new BinaryList()
.AddUInt8((byte)(0x28 | pv))
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ValueType.Compose())
.AddInt32(rexp.Length)
.AddUInt8Array(rexp)
.ToArray();
}
else
{
return new BinaryList()
.AddUInt8((byte)(0x20 | pv))
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ValueType.Compose())
.ToArray();
}
}
public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
RepresentationType valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false)
: base(template, index, name, inherited)
{
if (name == "RecordNullable")
Console.Beep();
this.Recordable = recordable;
//this.Storage = storage;
if (readAnnotation != null)
this.ReadAnnotation = readAnnotation;
this.WriteAnnotation = writeAnnotation;
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;
var propType = genericPropType == typeof(DistributedPropertyContext<>) ?
RepresentationType.FromType(pi.PropertyType.GetGenericArguments()[0]) :
RepresentationType.FromType(pi.PropertyType);
if (propType == null)
throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`");
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
var nullabilityContext = new NullabilityInfoContext();
propType.Nullable = nullabilityContext.Create(pi).ReadState is NullabilityState.Nullable;
// var nullableContextAttr = pi.GetCustomAttribute<NullableContextAttribute>(true);
// var nullableAttr = pi.GetCustomAttribute<NullableAttribute>(true);
// var flags = nullableAttr?.Flags?.ToList() ?? new List<byte>();
// 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);
// }
var pt = new PropertyTemplate(typeTemplate, index, customName ?? pi.Name, pi.DeclaringType != type, propType);
if (storageAttr != null)
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
if (annotationAttr != null)
pt.ReadAnnotation = annotationAttr.Annotation;
else
pt.ReadAnnotation = GetTypeAnnotationName(pi.PropertyType);
pt.PropertyInfo = pi;
return pt;
}
public static string GetTypeAnnotationName(Type type)
{
var nullType = Nullable.GetUnderlyingType(type);
if (nullType == null)
return type.Name;
else
return type.Name + "?";
}
}