Add ln.types.reflection

master
Harald Wolff 2020-02-24 17:26:38 +01:00
parent a008409bce
commit b02d62c4cb
9 changed files with 381 additions and 0 deletions

View File

@ -0,0 +1,10 @@
using System;
namespace ln.types.attributes
{
public class IdentityAttribute : Attribute
{
public IdentityAttribute()
{
}
}
}

View File

@ -139,6 +139,15 @@
<Compile Include="test\SchedulingPoolTests.cs" />
<Compile Include="text\TokenReader.cs" />
<Compile Include="io\LineWriter.cs" />
<Compile Include="reflection\AttributeDescriptor.cs" />
<Compile Include="reflection\TypeDescriptor.cs" />
<Compile Include="reflection\Reflector.cs" />
<Compile Include="reflection\ReflectedValue.cs" />
<Compile Include="collections\IDict.cs" />
<Compile Include="reflection\ObjectPoolContainer.cs" />
<Compile Include="reflection\ObjectPool.cs" />
<Compile Include="attributes\IdentityAttribute.cs" />
<Compile Include="reflection\ObjectPoolValue.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="odb\" />
@ -163,6 +172,8 @@
<Folder Include="odb\ng\diff\" />
<Folder Include="io\" />
<Folder Include="text\" />
<Folder Include="reflection\" />
<Folder Include="attributes\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.logging\ln.logging.csproj">

View File

@ -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<object, object> SetAction;
Func<object, object> 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);
}
}

View File

@ -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<object, object> getIdentity;
public object GetIdentity(object o) => getIdentity(o);
BTree<object, object> objects = new BTree<object, object>();
List<ObjectPool> derivedTypes = new List<ObjectPool>();
public ObjectPool(Type objectType, Type identityType, Func<object, object> getIdentityDelegate)
{
ObjectType = objectType;
IdentityType = identityType;
getIdentity = getIdentityDelegate;
}
public IEnumerable<object> Identities => objects.Keys;
public IEnumerable<object> 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);
}
}

View File

@ -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<string, ObjectPool> objectPools = new BTree<string, ObjectPool>();
public IEnumerable<ObjectPool> Pools => objectPools.Values;
public IEnumerable<Type> 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<IdentityAttribute>()!=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<IdentityAttribute>() != 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)
{
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<string> pElements = new Queue<string>(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<string> pElements = new Queue<string>(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<ReflectedValue> reflectedValues = new List<ReflectedValue>();
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<string>(path.Split('/')));
public static object GetValue(object o, Queue<string> 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<string>(path.Split('/')), value);
public static object SetValue(object o, Queue<string> 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);
}
}
*/
}
}

View File

@ -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<string, AttributeDescriptor> attributeDescriptors = new Dictionary<string, AttributeDescriptor>();
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<string> AttributeNames => attributeDescriptors.Keys;
public AttributeDescriptor GetAttributeDescriptor(string attributeName) => attributeDescriptors[attributeName];
public bool ContainsAttribute(string attributeName) => attributeDescriptors.ContainsKey(attributeName);
static Dictionary<Type, TypeDescriptor> typeDescriptors = new Dictionary<Type, TypeDescriptor>();
public static TypeDescriptor GetDescriptor(Type type)
{
if (typeDescriptors.TryGetValue(type, out TypeDescriptor typeDescriptor))
return new TypeDescriptor(type);
return typeDescriptor;
}
}
}