diff --git a/attributes/IdentityAttribute.cs b/attributes/IdentityAttribute.cs new file mode 100644 index 0000000..0f55e63 --- /dev/null +++ b/attributes/IdentityAttribute.cs @@ -0,0 +1,10 @@ +using System; +namespace ln.types.attributes +{ + public class IdentityAttribute : Attribute + { + public IdentityAttribute() + { + } + } +} diff --git a/ln.types.csproj b/ln.types.csproj index bb3b22f..37fda00 100644 --- a/ln.types.csproj +++ b/ln.types.csproj @@ -139,6 +139,15 @@ + + + + + + + + + @@ -163,6 +172,8 @@ + + diff --git a/reflection/AttributeDescriptor.cs b/reflection/AttributeDescriptor.cs new file mode 100644 index 0000000..ad5fd0b --- /dev/null +++ b/reflection/AttributeDescriptor.cs @@ -0,0 +1,54 @@ +// /** +// * File: AttributeDescriptor.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +using System.Reflection; +namespace ln.types.reflection +{ + public class AttributeDescriptor + { + public bool IsPublic { get; } + public bool IsReadonly { get; } + + public Type Owner { get; } + public string AttributeName { get; } + public Type AttributeType { get; } + + Action SetAction; + Func GetFunc; + + public AttributeDescriptor(PropertyInfo propertyInfo) + { + Owner = propertyInfo.DeclaringType; + IsPublic = propertyInfo.GetGetMethod().IsPublic; + IsReadonly = !(propertyInfo.CanWrite && propertyInfo.GetSetMethod().IsPublic); + AttributeName = propertyInfo.Name; + AttributeType = propertyInfo.PropertyType; + + SetAction = propertyInfo.SetValue; + GetFunc = propertyInfo.GetValue; + } + public AttributeDescriptor(FieldInfo fieldInfo) + { + Owner = fieldInfo.DeclaringType; + IsPublic = fieldInfo.IsPublic; + IsReadonly = fieldInfo.IsInitOnly; + AttributeName = fieldInfo.Name; + AttributeType = fieldInfo.FieldType; + + SetAction = fieldInfo.SetValue; + GetFunc = fieldInfo.GetValue; + } + + public TypeDescriptor TypeDescriptor => TypeDescriptor.GetDescriptor(Owner); + + public object GetValue(object instance) => GetFunc(instance); + public void SetValue(object instance, object value) => SetAction(instance, value); + } +} diff --git a/reflection/ObjectPool.cs b/reflection/ObjectPool.cs new file mode 100644 index 0000000..f2b8e8f --- /dev/null +++ b/reflection/ObjectPool.cs @@ -0,0 +1,42 @@ +using System; +using ln.types.btree; +using System.Collections.Generic; +namespace ln.types.reflection +{ + public class ObjectPool + { + public Type ObjectType { get; } + public Type IdentityType { get; } + + public TypeDescriptor TypeDescriptor => TypeDescriptor.GetDescriptor(ObjectType); + + Func getIdentity; + public object GetIdentity(object o) => getIdentity(o); + + BTree objects = new BTree(); + + List derivedTypes = new List(); + + public ObjectPool(Type objectType, Type identityType, Func getIdentityDelegate) + { + ObjectType = objectType; + IdentityType = identityType; + getIdentity = getIdentityDelegate; + } + + public IEnumerable Identities => objects.Keys; + public IEnumerable Instances => objects.Values; + + public object this[object identity] => objects[identity]; + + public void Add(object o) => objects.Add(GetIdentity(o), o); + public void Remove(object identity) => objects.Remove(identity); + + + public ObjectPoolValue GetValue(string attributePath) => throw new NotImplementedException(); + + public void AddDerivedTypePool(ObjectPool objectPool) => derivedTypes.Add(objectPool); + + + } +} diff --git a/reflection/ObjectPoolContainer.cs b/reflection/ObjectPoolContainer.cs new file mode 100644 index 0000000..5f88c0c --- /dev/null +++ b/reflection/ObjectPoolContainer.cs @@ -0,0 +1,54 @@ +using System; +using ln.types.btree; +using System.Reflection; +using ln.types.attributes; +using System.Collections.Generic; +using System.Linq; +namespace ln.types.reflection +{ + public class ObjectPoolContainer + { + BTree objectPools = new BTree(); + public IEnumerable Pools => objectPools.Values; + public IEnumerable Types => objectPools.Values.Select((pool) => pool.ObjectType); + + public ObjectPoolContainer() + { + } + + public ObjectPool this[string typeName] => objectPools[typeName]; + public ObjectPool this[Type type] => objectPools[type.Name]; + + public ObjectPoolContainer AddType(Type type) => AddType(type, null); + public ObjectPoolContainer AddType(Type type,String identityAttribute) + { + foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + { + if (((identityAttribute == null) && (fieldInfo.GetCustomAttribute()!=null)) || fieldInfo.Name.Equals(identityAttribute)) + { + objectPools.Add(type.Name, new ObjectPool(type, fieldInfo.FieldType, fieldInfo.GetValue)); + } + } + foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + { + if (((identityAttribute == null) && (propertyInfo.GetCustomAttribute() != null)) || propertyInfo.Name.Equals(identityAttribute)) + { + objectPools.Add(type.Name, new ObjectPool(type, propertyInfo.PropertyType, propertyInfo.GetValue)); + } + } + + SetupDerivedTypes(type); + + return this; + } + + public void SetupDerivedTypes(Type type) + { + + } + + + + + } +} diff --git a/reflection/ObjectPoolValue.cs b/reflection/ObjectPoolValue.cs new file mode 100644 index 0000000..e30d91e --- /dev/null +++ b/reflection/ObjectPoolValue.cs @@ -0,0 +1,19 @@ +using System; +namespace ln.types.reflection +{ + public class ObjectPoolValue + { + public ObjectPool ObjectPool { get; } + public object Value { get; } + + public string[] PathElements { get; } + public string Path => String.Join("/", PathElements); + + public ObjectPoolValue(ObjectPool objectPool,string[] pathElements,object value) + { + ObjectPool = objectPool; + PathElements = pathElements; + Value = value; + } + } +} diff --git a/reflection/ReflectedValue.cs b/reflection/ReflectedValue.cs new file mode 100644 index 0000000..d645585 --- /dev/null +++ b/reflection/ReflectedValue.cs @@ -0,0 +1,34 @@ +using System; + +namespace ln.types.reflection +{ + public class ReflectedValue + { + public ReflectedValue ReflectedOwner { get; } + public object Owner { get; } + + public AttributeDescriptor AttributeDescriptor { get; } + public object Value { get; private set; } + + public ReflectedValue(object owner, string attributeName) + { + Owner = owner; + AttributeDescriptor = TypeDescriptor.GetDescriptor(Owner.GetType()).GetAttributeDescriptor(attributeName); + Value = AttributeDescriptor.GetValue(Owner); + } + public ReflectedValue(ReflectedValue reflectedOwner, string attributeName) + { + ReflectedOwner = reflectedOwner; + Owner = reflectedOwner.Value; + AttributeDescriptor = TypeDescriptor.GetDescriptor(Owner.GetType()).GetAttributeDescriptor(attributeName); + Value = AttributeDescriptor.GetValue(Owner); + } + + public virtual void Replace(object value) + { + AttributeDescriptor.SetValue(Owner, value); + Value = value; + } + + } +} diff --git a/reflection/Reflector.cs b/reflection/Reflector.cs new file mode 100644 index 0000000..260e550 --- /dev/null +++ b/reflection/Reflector.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +namespace ln.types.reflection +{ + public static class Reflector + { + + public static void Get(object o, string path, out Type type, out object value) + { + Queue pElements = new Queue(path.Split('/')); + type = o.GetType(); + + while (pElements.Count > 0) + { + GetValue(o, pElements.Dequeue(), out type, out o); + } + value = o; + } + public static void Set(object o, string path, object value) + { + Queue pElements = new Queue(path.Split('/')); + Type valueType = null; + + while (pElements.Count > 1) + { + GetValue(o, pElements.Dequeue(), out valueType, out o); + } + + SetValue(o, pElements.Dequeue(), value); + } + + + + + public static void GetValue(object o, string attributeName,out Type valueType, out object value) + { + TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(o.GetType()); + AttributeDescriptor attributeDescriptor = typeDescriptor.GetAttributeDescriptor(attributeName); + valueType = attributeDescriptor.AttributeType; + value = attributeDescriptor.GetValue(o); + } + public static void SetValue(object o, string attributeName, object value) + { + TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(o.GetType()); + typeDescriptor.GetAttributeDescriptor(attributeName).SetValue(o, value); + } + + + /* + public static ReflectedValue[] Walk(object o,string path) + { + List reflectedValues = new List(); + + foreach (string pathElement in path.Split('/')) + { + ReflectedValue reflectedValue = new ReflectedValue(o, pathElement); + o = reflectedValue.Value; + reflectedValues.Add(reflectedValue); + } + + return reflectedValues.ToArray(); + } + + + public static object GetValue(object o, string path) => GetValue(o, new Queue(path.Split('/'))); + public static object GetValue(object o, Queue path) + { + while (path.Count > 0) + o = GetNext(o, path.Dequeue()); + return o; + } + public static object SetValue(object o, string path, object value) => SetValue(o, new Queue(path.Split('/')), value); + public static object SetValue(object o, Queue path, object value) + { + while (path.Count > 1) + o = GetNext(o, path.Dequeue()); + + return o; + } + + public static object GetNext(object o, string next) + { + if (o is Array) + { + throw new NotImplementedException(); + } + else + { + return GetAttributeValue(o, next); + } + } + public static void SetNext(object o, string next, object value) + { + if (o is Array) + { + throw new NotImplementedException(); + } + else + { + SetAttributeValue(o, next, value); + } + } + + + + + */ + + + + } +} diff --git a/reflection/TypeDescriptor.cs b/reflection/TypeDescriptor.cs new file mode 100644 index 0000000..6a146ca --- /dev/null +++ b/reflection/TypeDescriptor.cs @@ -0,0 +1,45 @@ +// /** +// * File: TypeDescriptor.cs +// * Author: haraldwolff +// * +// * This file and it's content is copyrighted by the Author and / or copyright holder. +// * Any use wihtout proper permission is illegal and may lead to legal actions. +// * +// * +// **/ +using System; +using System.Collections.Generic; +using System.Reflection; +namespace ln.types.reflection +{ + public class TypeDescriptor + { + public Type Type { get; } + + Dictionary attributeDescriptors = new Dictionary(); + + public TypeDescriptor(Type type) + { + typeDescriptors[type] = this; + + foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public)) + attributeDescriptors.Add(fieldInfo.Name, new AttributeDescriptor(fieldInfo)); + + foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) + attributeDescriptors.Add(propertyInfo.Name, new AttributeDescriptor(propertyInfo)); + + } + + public IEnumerable AttributeNames => attributeDescriptors.Keys; + public AttributeDescriptor GetAttributeDescriptor(string attributeName) => attributeDescriptors[attributeName]; + public bool ContainsAttribute(string attributeName) => attributeDescriptors.ContainsKey(attributeName); + + static Dictionary typeDescriptors = new Dictionary(); + public static TypeDescriptor GetDescriptor(Type type) + { + if (typeDescriptors.TryGetValue(type, out TypeDescriptor typeDescriptor)) + return new TypeDescriptor(type); + return typeDescriptor; + } + } +}