2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2026-01-27 01:20:39 +00:00
Files
esiur-dotnet/Esiur/Resource/Template/EventTemplate.cs
2026-01-19 18:38:34 +03:00

142 lines
4.9 KiB
C#

using Esiur.Core;
using Esiur.Data;
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 EventTemplate : MemberTemplate
{
public Map<string, string> Annotations
{
get;
set;
}
public override string ToString()
{
return $"{Name}: {ArgumentType}";
}
public bool Subscribable { get; set; }
public EventInfo EventInfo { get; set; }
public TRU ArgumentType { get; set; }
public override byte[] Compose()
{
var name = base.Compose();
var hdr = Inherited ? (byte)0x80 : (byte)0;
if (Subscribable)
hdr |= 0x8;
if (Annotations != null)
{
var exp = Codec.Compose(Annotations, null, null); //( DC.ToBytes(Annotation);
hdr |= 0x50;
return new BinaryList()
.AddUInt8(hdr)
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ArgumentType.Compose())
.AddInt32(exp.Length)
.AddUInt8Array(exp)
.ToArray();
}
else
hdr |= 0x40;
return new BinaryList()
.AddUInt8(hdr)
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ArgumentType.Compose())
.ToArray();
}
public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU argumentType, Map<string, string> annotations = null, bool subscribable = false)
: base(template, index, name, inherited)
{
this.Annotations = annotations;
this.Subscribable = subscribable;
this.ArgumentType = argumentType;
}
public static EventTemplate MakeEventTemplate(Type type, EventInfo ei, byte index = 0, string customName = null, TypeTemplate typeTemplate = null)
{
if (!ei.EventHandlerType.IsGenericType)
throw new Exception($"Unsupported event handler type in event `{type.Name}.{ei.Name}`");
if (ei.EventHandlerType.GetGenericTypeDefinition() != typeof(ResourceEventHandler<>)
&& ei.EventHandlerType.GetGenericTypeDefinition() != typeof(CustomResourceEventHandler<>))
throw new Exception($"Unsupported event handler type in event `{type.Name}.{ei.Name}`");
var argType = ei.EventHandlerType.GenericTypeArguments[0];
var evtType = TRU.FromType(argType);
if (evtType == null)
throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`");
var annotationAttrs = ei.GetCustomAttributes<AnnotationAttribute>(true);
var subscribableAttr = ei.GetCustomAttribute<SubscribableAttribute>(true);
//evtType.Nullable = new NullabilityInfoContext().Create(ei).ReadState is NullabilityState.Nullable;
var nullableAttr = ei.GetCustomAttributes().FirstOrDefault(x => x.GetType().Name == "System.Runtime.CompilerServices.NullableAttribute");// .GetCustomAttribute<NullableAttribute>(true);
var nullableContextAttr = ei.GetCustomAttributes().FirstOrDefault(x => x.GetType().Name == "System.Runtime.CompilerServices.NullableContextAttribute");// ei.GetCustomAttribute<NullableContextAttribute>(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<byte>();
//var flags = ((byte[])nullableAttr?.NullableFlags ?? new byte[0]).ToList();
// skip the eventHandler class
if (nullableAttrFlags.Count > 1)
nullableAttrFlags = nullableAttrFlags.Skip(1).ToList();
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;
if (annotationAttrs != null && annotationAttrs.Count() > 0)
{
et.Annotations = new Map<string, string>();
foreach (var attr in annotationAttrs)
et.Annotations.Add(attr.Key, attr.Value);
}
if (subscribableAttr != null)
et.Subscribable = true;
return et;
}
}