Add ln.types.reflection
parent
a008409bce
commit
b02d62c4cb
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
namespace ln.types.attributes
|
||||||
|
{
|
||||||
|
public class IdentityAttribute : Attribute
|
||||||
|
{
|
||||||
|
public IdentityAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -139,6 +139,15 @@
|
||||||
<Compile Include="test\SchedulingPoolTests.cs" />
|
<Compile Include="test\SchedulingPoolTests.cs" />
|
||||||
<Compile Include="text\TokenReader.cs" />
|
<Compile Include="text\TokenReader.cs" />
|
||||||
<Compile Include="io\LineWriter.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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="odb\" />
|
<Folder Include="odb\" />
|
||||||
|
@ -163,6 +172,8 @@
|
||||||
<Folder Include="odb\ng\diff\" />
|
<Folder Include="odb\ng\diff\" />
|
||||||
<Folder Include="io\" />
|
<Folder Include="io\" />
|
||||||
<Folder Include="text\" />
|
<Folder Include="text\" />
|
||||||
|
<Folder Include="reflection\" />
|
||||||
|
<Folder Include="attributes\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
|
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue