diff --git a/Cast.cs b/Cast.cs index e8ad79b..58f28c5 100644 --- a/Cast.cs +++ b/Cast.cs @@ -33,7 +33,30 @@ namespace ln.types !Explicit(value, value.GetType(), targetType, out casted) ) { - casted = Convert.ChangeType(value, targetType); + if (targetType.IsEnum) + { + if (value is string sValue) + { + casted = Enum.Parse(targetType, sValue); + } else + { + throw new NotSupportedException(); + } + } + else if (targetType.IsArray) + { + Array array = value as Array; + Array castedArray = Array.CreateInstance(targetType.GetElementType(), array.Length); + + for (int n = 0; n < array.Length; n++) + castedArray.SetValue(To(array.GetValue(n), targetType.GetElementType()), n); + + casted = castedArray; + } + else + { + casted = Convert.ChangeType(value, targetType); + } } return casted; } diff --git a/ln.types.csproj b/ln.types.csproj index 37fda00..7c6b08e 100644 --- a/ln.types.csproj +++ b/ln.types.csproj @@ -148,6 +148,7 @@ + diff --git a/reflection/AttributeDescriptor.cs b/reflection/AttributeDescriptor.cs index ad5fd0b..1b3d283 100644 --- a/reflection/AttributeDescriptor.cs +++ b/reflection/AttributeDescriptor.cs @@ -27,11 +27,13 @@ namespace ln.types.reflection { Owner = propertyInfo.DeclaringType; IsPublic = propertyInfo.GetGetMethod().IsPublic; - IsReadonly = !(propertyInfo.CanWrite && propertyInfo.GetSetMethod().IsPublic); + IsReadonly = !(propertyInfo.CanWrite && propertyInfo.GetSetMethod(true).IsPublic); AttributeName = propertyInfo.Name; AttributeType = propertyInfo.PropertyType; - SetAction = propertyInfo.SetValue; + if (propertyInfo.CanWrite) + SetAction = propertyInfo.SetValue; + GetFunc = propertyInfo.GetValue; } public AttributeDescriptor(FieldInfo fieldInfo) @@ -42,13 +44,18 @@ namespace ln.types.reflection AttributeName = fieldInfo.Name; AttributeType = fieldInfo.FieldType; - SetAction = fieldInfo.SetValue; + if (!fieldInfo.IsInitOnly) + 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); + public void SetValue(object instance, object value) { + if (SetAction != null) + SetAction(instance, value); + } } } diff --git a/reflection/ObjectPool.cs b/reflection/ObjectPool.cs index f2b8e8f..8a72467 100644 --- a/reflection/ObjectPool.cs +++ b/reflection/ObjectPool.cs @@ -1,6 +1,7 @@ using System; using ln.types.btree; using System.Collections.Generic; +using System.Linq; namespace ln.types.reflection { public class ObjectPool @@ -24,10 +25,22 @@ namespace ln.types.reflection getIdentity = getIdentityDelegate; } - public IEnumerable Identities => objects.Keys; - public IEnumerable Instances => objects.Values; + public IEnumerable Identities => objects.Keys.Concat(derivedTypes.SelectMany((op)=>op.Identities)); + public IEnumerable Instances => objects.Values.Concat(derivedTypes.SelectMany((op) => op.Instances)); + public IEnumerable OwnInstances => objects.Values; - public object this[object identity] => objects[identity]; + public object this[object identity] + { + get + { + if (objects.ContainsKey(identity)) + return objects[identity]; + foreach (ObjectPool derivedPool in derivedTypes) + if (derivedPool.objects.ContainsKey(identity)) + return derivedPool.objects[identity]; + throw new KeyNotFoundException(); + } + } public void Add(object o) => objects.Add(GetIdentity(o), o); public void Remove(object identity) => objects.Remove(identity); diff --git a/reflection/ObjectPoolContainer.cs b/reflection/ObjectPoolContainer.cs index 5f88c0c..367f4c4 100644 --- a/reflection/ObjectPoolContainer.cs +++ b/reflection/ObjectPoolContainer.cs @@ -19,6 +19,8 @@ namespace ln.types.reflection public ObjectPool this[string typeName] => objectPools[typeName]; public ObjectPool this[Type type] => objectPools[type.Name]; + public bool KnowsType(Type type) => objectPools.ContainsKey(type.Name); + public ObjectPoolContainer AddType(Type type) => AddType(type, null); public ObjectPoolContainer AddType(Type type,String identityAttribute) { @@ -44,7 +46,17 @@ namespace ln.types.reflection public void SetupDerivedTypes(Type type) { + Type current = type.BaseType; + while (!object.Equals(current, typeof(object))) + { + if (objectPools.ContainsKey(current.Name)) + { + objectPools[current.Name].AddDerivedTypePool(objectPools[type.Name]); + break; + } + current = current.BaseType; + } } diff --git a/reflection/TypeDescriptor.cs b/reflection/TypeDescriptor.cs index 6a146ca..2f1f91a 100644 --- a/reflection/TypeDescriptor.cs +++ b/reflection/TypeDescriptor.cs @@ -20,6 +20,8 @@ namespace ln.types.reflection public TypeDescriptor(Type type) { + Type = type; + typeDescriptors[type] = this; foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public)) @@ -31,13 +33,15 @@ namespace ln.types.reflection } public IEnumerable AttributeNames => attributeDescriptors.Keys; + public IEnumerable AttributeDescriptors => attributeDescriptors.Values; 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)) + if (!typeDescriptors.TryGetValue(type, out TypeDescriptor typeDescriptor)) return new TypeDescriptor(type); return typeDescriptor; } diff --git a/reflection/TypeExtensions.cs b/reflection/TypeExtensions.cs new file mode 100644 index 0000000..e94d6f9 --- /dev/null +++ b/reflection/TypeExtensions.cs @@ -0,0 +1,21 @@ +using System; +using System.Linq; +namespace ln.types.reflection +{ + public static class TypeExtensions + { + + public static bool HasGenericInterface(this Type type) => HasGenericInterface(type, typeof(T).GetGenericTypeDefinition()); + public static bool HasGenericInterface(this Type type, Type genericInterfaceType) + { + return type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericInterfaceType); + } + + public static Type GetGenericInterface(this Type type) => GetGenericInterface(type, typeof(T).GetGenericTypeDefinition()); + public static Type GetGenericInterface(this Type type, Type genericInterfaceType) + { + return type.GetInterfaces().First(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericInterfaceType); + } + + } +} diff --git a/threads/SchedulingPool.cs b/threads/SchedulingPool.cs index 0dcdc2d..13f3990 100644 --- a/threads/SchedulingPool.cs +++ b/threads/SchedulingPool.cs @@ -47,15 +47,22 @@ namespace ln.types.threads ThreadPool = new Pool(nThreads); ThreadPool.Start(); - schedulerThread = new Thread(scheduler); - schedulerThread.Start(); + lock (this) + { + schedulerThread = new Thread(scheduler); + schedulerThread.Start(); + + Monitor.Wait(this); + } } void scheduler() { - while (true) + lock (this) { - lock (this) + Monitor.PulseAll(this); + + while (true) { double now = DateTime.Now.ToUnixTimeMilliseconds(); if (schedule.Empty)