mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 19:42:58 +00:00
GetHierarchy
This commit is contained in:
parent
ebcf8525fa
commit
acc2a546cf
@ -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)
|
|
||||||
{
|
|
||||||
|
|
||||||
foreach (var ci in constantsInfo)
|
|
||||||
{
|
{
|
||||||
var privateAttr = ci.GetCustomAttribute<PrivateAttribute>(true);
|
constants.Add(ConstantTemplate.MakeConstantTemplate
|
||||||
|
(type, (FieldInfo)cd.GetMemberInfo(), cd.Index, cd.Name, this));
|
||||||
if (privateAttr != null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var publicAttr = ci.GetCustomAttribute<PublicAttribute>(true);
|
|
||||||
|
|
||||||
var ct = MakeConstantTemplate(type, ci, publicAttr, (byte)constants.Count, this);
|
|
||||||
constants.Add(ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var pi in propsInfo)
|
|
||||||
{
|
|
||||||
var privateAttr = pi.GetCustomAttribute<PrivateAttribute>(true);
|
|
||||||
|
|
||||||
if (privateAttr == null)
|
|
||||||
{
|
|
||||||
var publicAttr = pi.GetCustomAttribute<PublicAttribute>(true);
|
|
||||||
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
|
|
||||||
|| templateType == TemplateType.Wrapper)
|
|
||||||
{
|
|
||||||
|
|
||||||
foreach (var ei in eventsInfo)
|
|
||||||
{
|
|
||||||
var privateAttr = ei.GetCustomAttribute<PrivateAttribute>(true);
|
|
||||||
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);
|
|
||||||
if (privateAttr != null)
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var ci in constantsInfo)
|
|
||||||
{
|
|
||||||
var publicAttr = ci.GetCustomAttribute<PublicAttribute>(true);
|
|
||||||
|
|
||||||
if (publicAttr == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var ct = MakeConstantTemplate(type, ci, publicAttr, (byte)constants.Count, this);
|
|
||||||
constants.Add(ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var pi in propsInfo)
|
|
||||||
{
|
|
||||||
var publicAttr = pi.GetCustomAttribute<PublicAttribute>(true);
|
|
||||||
|
|
||||||
if (publicAttr != null)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
|| 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
|
if (hierarchy.ContainsKey(MemberTypes.Property))
|
||||||
|
{
|
||||||
|
foreach (var pd in hierarchy[MemberTypes.Property])
|
||||||
|
{
|
||||||
|
properties.Add(PropertyTemplate.MakePropertyTemplate
|
||||||
|
(type, (PropertyInfo)pd.GetMemberInfo(), pd.Index, pd.Name, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (templateType == TemplateType.Resource
|
||||||
|
|| templateType == TemplateType.Wrapper)
|
||||||
|
{
|
||||||
|
if (hierarchy.ContainsKey(MemberTypes.Method))
|
||||||
|
{
|
||||||
|
foreach (var fd in hierarchy[MemberTypes.Method])
|
||||||
|
{
|
||||||
|
functions.Add(FunctionTemplate.MakeFunctionTemplate
|
||||||
|
(type, (MethodInfo)fd.GetMemberInfo(), fd.Index, fd.Name, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hierarchy.ContainsKey(MemberTypes.Event))
|
||||||
|
{
|
||||||
|
foreach (var ed in hierarchy[MemberTypes.Event])
|
||||||
|
{
|
||||||
|
events.Add(EventTemplate.MakeEventTemplate
|
||||||
|
(type, (EventInfo)ed.GetMemberInfo(), ed.Index, ed.Name, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// add attributes
|
||||||
|
var attrs = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||||
|
.Where(x => x.GetCustomAttribute<AttributeAttribute>() != null);
|
||||||
|
|
||||||
|
foreach (var attr in attrs)
|
||||||
|
{
|
||||||
|
var attrAttr = attr.GetCustomAttribute<AttributeAttribute>();
|
||||||
|
|
||||||
|
attributes.Add(AttributeTemplate
|
||||||
|
.MakeAttributeTemplate(type, attr, 0, attrAttr?.Name ?? attr.Name, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
if (parent == typeof(Resource)
|
|
||||||
|| parent == typeof(Record)
|
|
||||||
|| parent == typeof(EntryPoint))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
while (parent != null)
|
while (parent != null)
|
||||||
{
|
{
|
||||||
|
if (parent == typeof(Resource)
|
||||||
|
|| parent == typeof(Record)
|
||||||
|
|| parent == typeof(EntryPoint))
|
||||||
|
return false;
|
||||||
|
|
||||||
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]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user