mirror of
				https://github.com/esiur/esiur-dotnet.git
				synced 2025-10-31 16:01:34 +00:00 
			
		
		
		
	GetHierarchy
This commit is contained in:
		| @@ -6,7 +6,7 @@ | |||||||
|     <Copyright>Ahmed Kh. Zamil</Copyright> |     <Copyright>Ahmed Kh. Zamil</Copyright> | ||||||
|      <PackageProjectUrl>http://www.esiur.com</PackageProjectUrl> |      <PackageProjectUrl>http://www.esiur.com</PackageProjectUrl> | ||||||
|     <GeneratePackageOnBuild>true</GeneratePackageOnBuild> |     <GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||||
|     <Version>2.2.8</Version> |     <Version>2.2.9</Version> | ||||||
|     <RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl> |     <RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl> | ||||||
|     <Authors>Ahmed Kh. Zamil</Authors> |     <Authors>Ahmed Kh. Zamil</Authors> | ||||||
|     <AssemblyVersion></AssemblyVersion> |     <AssemblyVersion></AssemblyVersion> | ||||||
|   | |||||||
| @@ -21,4 +21,11 @@ public class AttributeTemplate : MemberTemplate | |||||||
|     { |     { | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public static AttributeTemplate MakeAttributeTemplate(Type type, PropertyInfo pi, byte index = 0, string customName = null, TypeTemplate typeTemplate = null) | ||||||
|  |     { | ||||||
|  |         var at = new AttributeTemplate(typeTemplate, index, customName, pi.DeclaringType != type); | ||||||
|  |         at.PropertyInfo = pi; | ||||||
|  |         return at; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ public class ConstantTemplate : MemberTemplate | |||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     public static ConstantTemplate MakeConstantTemplate(Type type, FieldInfo ci, PublicAttribute publicAttr, byte index = 0, TypeTemplate typeTemplate = null) |     public static ConstantTemplate MakeConstantTemplate(Type type, FieldInfo ci, byte index = 0, string customName = null, TypeTemplate typeTemplate = null) | ||||||
|     { |     { | ||||||
|         var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true); |         var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true); | ||||||
|         var nullableAttr = ci.GetCustomAttribute<NullableAttribute>(true); |         var nullableAttr = ci.GetCustomAttribute<NullableAttribute>(true); | ||||||
| @@ -84,7 +84,7 @@ public class ConstantTemplate : MemberTemplate | |||||||
|         if (typeTemplate?.Type == TemplateType.Enum) |         if (typeTemplate?.Type == TemplateType.Enum) | ||||||
|             value = Convert.ChangeType(value, ci.FieldType.GetEnumUnderlyingType()); |             value = Convert.ChangeType(value, ci.FieldType.GetEnumUnderlyingType()); | ||||||
|  |  | ||||||
|         var ct = new ConstantTemplate(typeTemplate, index, publicAttr?.Name ?? ci.Name, ci.DeclaringType != type, valueType, value, annotationAttr?.Annotation); |         var ct = new ConstantTemplate(typeTemplate, index, customName ?? ci.Name, ci.DeclaringType != type, valueType, value, annotationAttr?.Annotation); | ||||||
|         ct.FieldInfo = ci; |         ct.FieldInfo = ci; | ||||||
|  |  | ||||||
|         return ct; |         return ct; | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								Esiur/Resource/Template/MemberData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								Esiur/Resource/Template/MemberData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Reflection; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
|  | namespace Esiur.Resource.Template; | ||||||
|  |  | ||||||
|  | public class MemberData | ||||||
|  | { | ||||||
|  |     public MemberInfo Info; | ||||||
|  |     public string Name; | ||||||
|  |     public int Order; | ||||||
|  |     //public bool Inherited; | ||||||
|  |     public MemberData? Parent; | ||||||
|  |     public MemberData? Child; | ||||||
|  |     public byte Index; | ||||||
|  |  | ||||||
|  |     public MemberInfo GetMemberInfo() | ||||||
|  |     { | ||||||
|  |         var rt = Info; | ||||||
|  |         var md = Child; | ||||||
|  |         while (md != null) | ||||||
|  |         { | ||||||
|  |             rt = Info; | ||||||
|  |             md = md.Child; | ||||||
|  |         } | ||||||
|  |         return rt; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public string? GetAnnotation() | ||||||
|  |     { | ||||||
|  |         string rt = null; | ||||||
|  |         var md = this; | ||||||
|  |         while (md != null) | ||||||
|  |         { | ||||||
|  |             var annotationAttr = md.Info.GetCustomAttribute<AnnotationAttribute>(); | ||||||
|  |             if (annotationAttr != null) | ||||||
|  |                 rt = annotationAttr.Annotation; | ||||||
|  |             md = md.Child; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return rt; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -426,158 +426,71 @@ public class TypeTemplate | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); |         //PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); | ||||||
|         EventInfo[] eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.Instance); |         //EventInfo[] eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.Instance); | ||||||
|         MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); |         //MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); | ||||||
|         FieldInfo[] constantsInfo = type.GetFields(BindingFlags.Public | BindingFlags.Static); |         //FieldInfo[] constantsInfo = type.GetFields(BindingFlags.Public | BindingFlags.Static); | ||||||
|  |  | ||||||
|  |  | ||||||
|         bool classIsPublic = type.IsEnum || (type.GetCustomAttribute<PublicAttribute>() != null); |         //bool classIsPublic = type.IsEnum || (type.GetCustomAttribute<PublicAttribute>() != null); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         var hierarchy = GetHierarchy(type); | ||||||
|  |  | ||||||
|  |         if (hierarchy.ContainsKey(MemberTypes.Field)) | ||||||
|         |  | ||||||
|         var addAttribute = (PropertyInfo pi, AttributeAttribute attributeAttr) => |  | ||||||
|         { |         { | ||||||
|             var an = attributeAttr.Name ?? pi.Name; |             foreach (var cd in hierarchy[MemberTypes.Field]) | ||||||
|             var at = new AttributeTemplate(this, 0, an, pi.DeclaringType != type); |  | ||||||
|             at.PropertyInfo = pi; |  | ||||||
|             attributes.Add(at); |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         if (classIsPublic) |  | ||||||
|             { |             { | ||||||
|  |                 constants.Add(ConstantTemplate.MakeConstantTemplate | ||||||
|             foreach (var ci in constantsInfo) |                     (type, (FieldInfo)cd.GetMemberInfo(), cd.Index, cd.Name, this)); | ||||||
|             { |             } | ||||||
|                 var privateAttr = ci.GetCustomAttribute<PrivateAttribute>(true); |  | ||||||
|  |  | ||||||
|                 if (privateAttr != null) |  | ||||||
|                     continue; |  | ||||||
|  |  | ||||||
|                 var publicAttr = ci.GetCustomAttribute<PublicAttribute>(true); |  | ||||||
|  |  | ||||||
|                 var ct = MakeConstantTemplate(type, ci, publicAttr, (byte)constants.Count, this); |  | ||||||
|                 constants.Add(ct); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (hierarchy.ContainsKey(MemberTypes.Property)) | ||||||
|             foreach (var pi in propsInfo) |  | ||||||
|         { |         { | ||||||
|                 var privateAttr = pi.GetCustomAttribute<PrivateAttribute>(true); |             foreach (var pd in hierarchy[MemberTypes.Property]) | ||||||
|  |  | ||||||
|                 if (privateAttr == null) |  | ||||||
|             { |             { | ||||||
|                     var publicAttr = pi.GetCustomAttribute<PublicAttribute>(true); |                 properties.Add(PropertyTemplate.MakePropertyTemplate | ||||||
|                     var pt = PropertyTemplate.MakePropertyTemplate(type, pi, (byte)properties.Count, publicAttr?.Name, this); |                     (type, (PropertyInfo)pd.GetMemberInfo(), pd.Index, pd.Name, this)); | ||||||
|                     properties.Add(pt); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     var attributeAttr = pi.GetCustomAttribute<AttributeAttribute>(true); |  | ||||||
|                     if (attributeAttr != null) |  | ||||||
|                     { |  | ||||||
|                         addAttribute(pi, attributeAttr); |  | ||||||
|                     } |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (templateType == TemplateType.Resource |         if (templateType == TemplateType.Resource | ||||||
|             || templateType == TemplateType.Wrapper) |             || templateType == TemplateType.Wrapper) | ||||||
|         { |         { | ||||||
|  |             if (hierarchy.ContainsKey(MemberTypes.Method)) | ||||||
|                 foreach (var ei in eventsInfo) |  | ||||||
|             { |             { | ||||||
|                     var privateAttr = ei.GetCustomAttribute<PrivateAttribute>(true); |                 foreach (var fd in hierarchy[MemberTypes.Method]) | ||||||
|                     if (privateAttr != null) |  | ||||||
|                         continue; |  | ||||||
|  |  | ||||||
|                     var publicAttr = ei.GetCustomAttribute<PublicAttribute>(true); |  | ||||||
|                     var et = EventTemplate.MakeEventTemplate(type, ei, (byte)events.Count, publicAttr?.Name, this); |  | ||||||
|                     events.Add(et); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 foreach (MethodInfo mi in methodsInfo) |  | ||||||
|                 { |                 { | ||||||
|                     var privateAttr = mi.GetCustomAttribute<PrivateAttribute>(true); |                     functions.Add(FunctionTemplate.MakeFunctionTemplate | ||||||
|                     if (privateAttr != null) |                         (type, (MethodInfo)fd.GetMemberInfo(), fd.Index, fd.Name, this)); | ||||||
|                         continue; |                 } | ||||||
|  |  | ||||||
|                     var publicAttr = mi.GetCustomAttribute<PublicAttribute>(true); |  | ||||||
|                     var ft = FunctionTemplate.MakeFunctionTemplate(type, mi, (byte)functions.Count, publicAttr?.Name, this); |  | ||||||
|                     functions.Add(ft); |  | ||||||
|                     //addFunction(mi, publicAttr); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             } |             if (hierarchy.ContainsKey(MemberTypes.Event)) | ||||||
|         } |  | ||||||
|         else |  | ||||||
|             { |             { | ||||||
|             foreach (var ci in constantsInfo) |                 foreach (var ed in hierarchy[MemberTypes.Event]) | ||||||
|                 { |                 { | ||||||
|                 var publicAttr = ci.GetCustomAttribute<PublicAttribute>(true); |                     events.Add(EventTemplate.MakeEventTemplate | ||||||
|  |                         (type, (EventInfo)ed.GetMemberInfo(), ed.Index, ed.Name, this)); | ||||||
|                 if (publicAttr == null) |                 } | ||||||
|                     continue; |  | ||||||
|  |  | ||||||
|                 var ct = MakeConstantTemplate(type, ci, publicAttr, (byte)constants.Count, this); |  | ||||||
|                 constants.Add(ct); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|             foreach (var pi in propsInfo) |         // add attributes | ||||||
|  |         var attrs = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) | ||||||
|  |             .Where(x => x.GetCustomAttribute<AttributeAttribute>() != null); | ||||||
|  |  | ||||||
|  |         foreach (var attr in attrs) | ||||||
|         { |         { | ||||||
|                 var publicAttr = pi.GetCustomAttribute<PublicAttribute>(true); |             var attrAttr = attr.GetCustomAttribute<AttributeAttribute>(); | ||||||
|  |  | ||||||
|                 if (publicAttr != null) |             attributes.Add(AttributeTemplate | ||||||
|                 { |                 .MakeAttributeTemplate(type, attr, 0, attrAttr?.Name ?? attr.Name, this)); | ||||||
|                     var pt = PropertyTemplate.MakePropertyTemplate(type, pi, (byte)properties.Count, publicAttr?.Name, this); |  | ||||||
|                     properties.Add(pt); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     var attributeAttr = pi.GetCustomAttribute<AttributeAttribute>(true); |  | ||||||
|                     if (attributeAttr != null) |  | ||||||
|                     { |  | ||||||
|                         addAttribute(pi, attributeAttr); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|             if (templateType == TemplateType.Resource |         // append signals) | ||||||
|                 || templateType == TemplateType.Wrapper) |  | ||||||
|             { |  | ||||||
|  |  | ||||||
|                 foreach (var ei in eventsInfo) |  | ||||||
|                 { |  | ||||||
|                     var publicAttr = ei.GetCustomAttribute<PublicAttribute>(true); |  | ||||||
|  |  | ||||||
|                     if (publicAttr == null) |  | ||||||
|                         continue; |  | ||||||
|  |  | ||||||
|                     var et = EventTemplate.MakeEventTemplate(type, ei, (byte)events.Count, publicAttr?.Name, this); |  | ||||||
|                     events.Add(et); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 foreach (MethodInfo mi in methodsInfo) |  | ||||||
|                 { |  | ||||||
|                     var publicAttr = mi.GetCustomAttribute<PublicAttribute>(true); |  | ||||||
|                     if (publicAttr == null) |  | ||||||
|                         continue; |  | ||||||
|  |  | ||||||
|                     var ft = FunctionTemplate.MakeFunctionTemplate(type, mi, (byte)functions.Count, publicAttr?.Name, this); |  | ||||||
|                     functions.Add(ft); |  | ||||||
|                     //addFunction(mi, publicAttr); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // append signals |  | ||||||
|         for (var i = 0; i < events.Count; i++) |         for (var i = 0; i < events.Count; i++) | ||||||
|             members.Add(events[i]); |             members.Add(events[i]); | ||||||
|         // append slots |         // append slots | ||||||
| @@ -645,22 +558,146 @@ public class TypeTemplate | |||||||
|     { |     { | ||||||
|         var parent = type.BaseType; |         var parent = type.BaseType; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         while (parent != null) | ||||||
|  |         { | ||||||
|             if (parent == typeof(Resource) |             if (parent == typeof(Resource) | ||||||
|                 || parent == typeof(Record) |                 || parent == typeof(Record) | ||||||
|                 || parent == typeof(EntryPoint)) |                 || parent == typeof(EntryPoint)) | ||||||
|                 return false; |                 return false; | ||||||
|  |  | ||||||
|         while (parent != null) |  | ||||||
|         { |  | ||||||
|             if (parent.GetInterfaces().Contains(typeof(IResource)) |             if (parent.GetInterfaces().Contains(typeof(IResource)) | ||||||
|                 || parent.GetInterfaces().Contains(typeof(IRecord))) |                 || parent.GetInterfaces().Contains(typeof(IRecord))) | ||||||
|                 return true; |                 return true; | ||||||
|  |  | ||||||
|             parent = parent.BaseType; |             parent = parent.BaseType; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     public static Dictionary<MemberTypes, List<MemberData>> GetHierarchy(Type type) | ||||||
|  |     { | ||||||
|  |         var members = new List<MemberData>(); | ||||||
|  |  | ||||||
|  |         var order = 0; | ||||||
|  |  | ||||||
|  |         while (type != null) | ||||||
|  |         { | ||||||
|  |             var classIsPublic = type.IsEnum || (type.GetCustomAttribute<PublicAttribute>() != null); | ||||||
|  |  | ||||||
|  |             if (classIsPublic) | ||||||
|  |             { | ||||||
|  |                 var mis = type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) | ||||||
|  |                     .Where(x => x.MemberType == MemberTypes.Property || x.MemberType == MemberTypes.Field | ||||||
|  |                             || x.MemberType == MemberTypes.Event || x.MemberType == MemberTypes.Method) | ||||||
|  |                     .Where(x => !(x is FieldInfo c && !c.IsStatic)) | ||||||
|  |                     .Where(x => x.GetCustomAttribute<PrivateAttribute>() == null) | ||||||
|  |                     .Where(x => !(x is MethodInfo m && m.IsSpecialName)) | ||||||
|  |                     .Select(x => new MemberData() | ||||||
|  |                     { | ||||||
|  |                         Name = x.GetCustomAttribute<PublicAttribute>()?.Name ?? x.Name, | ||||||
|  |                         Info = x, | ||||||
|  |                         Order = order | ||||||
|  |                     }) | ||||||
|  |                     .OrderBy(x => x.Name); | ||||||
|  |  | ||||||
|  |                 members.AddRange(mis.ToArray()); | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 var mis = type.GetMembers(BindingFlags.Public | BindingFlags.Instance | ||||||
|  |                     | BindingFlags.DeclaredOnly | BindingFlags.Static) | ||||||
|  |                     .Where(x => x.MemberType == MemberTypes.Property || x.MemberType == MemberTypes.Field | ||||||
|  |                             || x.MemberType == MemberTypes.Event || x.MemberType == MemberTypes.Method) | ||||||
|  |                     .Where(x => !(x is FieldInfo c && !c.IsStatic)) | ||||||
|  |                     .Where(x => x.GetCustomAttribute<PublicAttribute>() != null) | ||||||
|  |                     .Where(x => !(x is MethodInfo m && m.IsSpecialName)) | ||||||
|  |                     .Select(x => new MemberData | ||||||
|  |                     { | ||||||
|  |                         Name = x.GetCustomAttribute<PublicAttribute>()?.Name ?? x.Name, | ||||||
|  |                         Info = x, | ||||||
|  |                         Order = order | ||||||
|  |                     }) | ||||||
|  |                     .OrderBy(x => x.Name); | ||||||
|  |  | ||||||
|  |                 members.AddRange(mis.ToArray()); | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             type = type.BaseType; | ||||||
|  |  | ||||||
|  |             if (type == typeof(Resource) | ||||||
|  |                 || type == typeof(Record) | ||||||
|  |                 || type == typeof(EntryPoint)) | ||||||
|  |                 break; | ||||||
|  |  | ||||||
|  |             if (type.GetInterfaces().Contains(typeof(IResource)) | ||||||
|  |                 || type.GetInterfaces().Contains(typeof(IRecord))) | ||||||
|  |             { | ||||||
|  |                 order++; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // round 2: check for duplicates | ||||||
|  |         for (var i = 0; i < members.Count; i++) | ||||||
|  |         { | ||||||
|  |             var mi = members[i]; | ||||||
|  |             for (var j = i + 1; j < members.Count; j++) | ||||||
|  |             { | ||||||
|  |                 var pi = members[j]; | ||||||
|  |                 if (pi.Info.MemberType != mi.Info.MemberType) | ||||||
|  |                     continue; | ||||||
|  |  | ||||||
|  |                 //if (ci.Info.Name == mi.Info.Name && ci.Order == mi.Order) | ||||||
|  |                 //    throw new Exception($"Method overload is not supported. Method '{ci.Info.Name}'."); | ||||||
|  |  | ||||||
|  |                 if (pi.Name == mi.Name) | ||||||
|  |                 { | ||||||
|  |                     if (pi.Order == mi.Order) | ||||||
|  |                         throw new Exception($"Duplicate definitions for members public name '{mi.Info.DeclaringType.Name}:{mi.Info.Name}' and '{pi.Info.DeclaringType.Name}:{pi.Info.Name}'."); | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         // @TODO: check for return type and parameters they must match | ||||||
|  |                         if (pi.Info.Name != mi.Info.Name) | ||||||
|  |                             throw new Exception($"Duplicate definitions for members public name '{mi.Info.DeclaringType.Name}:{mi.Info.Name}' and '{pi.Info.DeclaringType.Name}:{pi.Info.Name}'."); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     mi.Parent = pi; | ||||||
|  |                     pi.Child = mi; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         // assign indexies | ||||||
|  |         var groups = members.Where(x => x.Parent == null) | ||||||
|  |                             .OrderBy(x => x.Name).OrderByDescending(x => x.Order) | ||||||
|  |                             .GroupBy(x => x.Info.MemberType); | ||||||
|  |  | ||||||
|  |         foreach (var group in groups) | ||||||
|  |         { | ||||||
|  |             byte index = 0; | ||||||
|  |             foreach (var mi in group) | ||||||
|  |             { | ||||||
|  |                 //if (mi.Parent == null) | ||||||
|  |                 mi.Index = index++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         var rt = groups.ToDictionary(g => g.Key, g => g.ToList()); | ||||||
|  |  | ||||||
|  |         return rt; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     public static TypeTemplate Parse(byte[] data) |     public static TypeTemplate Parse(byte[] data) | ||||||
|     { |     { | ||||||
|         return Parse(data, 0, (uint)data.Length); |         return Parse(data, 0, (uint)data.Length); | ||||||
|   | |||||||
| @@ -11,5 +11,6 @@ namespace Test | |||||||
|     public class MyChildRecord : MyRecord |     public class MyChildRecord : MyRecord | ||||||
|     { |     { | ||||||
|         public string ChildName { get; set; } |         public string ChildName { get; set; } | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,6 +11,10 @@ namespace Test | |||||||
|     public partial class MyChildResource : MyResource |     public partial class MyChildResource : MyResource | ||||||
|     { |     { | ||||||
|         [Public] string childName; |         [Public] string childName; | ||||||
|         [Public] public int ChildMethod(string childName) => 111; |         [Public("Hell2o")] public int ChildMethod(string childName) => 111; | ||||||
|  |         [Public] public new string Hello() => "Hi from Child"; | ||||||
|  |  | ||||||
|  |         [Public] public string HelloChild() => "Hi from Child"; | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,5 +13,11 @@ namespace Test | |||||||
|     { |     { | ||||||
|         [Public][Annotation("Comment")] string description; |         [Public][Annotation("Comment")] string description; | ||||||
|         [Public] int categoryId; |         [Public] int categoryId; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         [Public] public string Hello() => "Hi"; | ||||||
|  |  | ||||||
|  |         [Public] public string HelloParent() => "Hi from Parent"; | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ using System.Runtime.CompilerServices; | |||||||
| using Esiur.Proxy; | using Esiur.Proxy; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.Reflection; | ||||||
|  |  | ||||||
| namespace Test | namespace Test | ||||||
| { | { | ||||||
| @@ -54,6 +55,10 @@ namespace Test | |||||||
|         static async Task Main(string[] args) |         static async Task Main(string[] args) | ||||||
|         { |         { | ||||||
|  |  | ||||||
|  |             var ppp = GetOrderedProperties(typeof(MyChildResource)).ToArray(); | ||||||
|  |             var childMethods = typeof(MyChildResource).GetMembers( BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance); | ||||||
|  |             var parentMethods = typeof(MyResource).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance); | ||||||
|  |  | ||||||
|             // Create stores to keep objects. |             // Create stores to keep objects. | ||||||
|             var system = await Warehouse.Put("sys", new MemoryStore()); |             var system = await Warehouse.Put("sys", new MemoryStore()); | ||||||
|             var server = await Warehouse.Put("sys/server", new DistributedServer()); |             var server = await Warehouse.Put("sys/server", new DistributedServer()); | ||||||
| @@ -222,6 +227,28 @@ namespace Test | |||||||
|                 return value.ToString(); |                 return value.ToString(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   | ||||||
|  |  | ||||||
|  |         public static IEnumerable<PropertyInfo> GetOrderedProperties(Type type) | ||||||
|  |         { | ||||||
|  |             Dictionary<Type, int> lookup = new Dictionary<Type, int>(); | ||||||
|  |  | ||||||
|  |             int count = 0; | ||||||
|  |             lookup[type] = count++; | ||||||
|  |             Type parent = type.BaseType; | ||||||
|  |             while (parent != null) | ||||||
|  |             { | ||||||
|  |                 lookup[parent] = count; | ||||||
|  |                 count++; | ||||||
|  |                 parent = parent.BaseType; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return type.GetProperties() | ||||||
|  |                 .OrderByDescending(prop => lookup[prop.DeclaringType]); | ||||||
|  |         } | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user