diff --git a/src/DryIoc/Container.cs b/src/DryIoc/Container.cs
index 4540239b1..a35b5ca22 100644
--- a/src/DryIoc/Container.cs
+++ b/src/DryIoc/Container.cs
@@ -52,6 +52,7 @@ namespace DryIoc
using System.Threading;
using System.Diagnostics.CodeAnalysis; // for SuppressMessage
using System.Diagnostics; // for StackTrace
+ using System.Runtime.CompilerServices; // for MethodImplAttribute
using ImTools;
using static ImTools.ArrayTools;
@@ -8216,13 +8217,18 @@ public static partial class PropertiesAndFields
/// Says to include properties of primitive type.
/// True if property is matched and false otherwise.
public static bool IsInjectable(this PropertyInfo property,
- bool withNonPublic = false, bool withPrimitive = false) =>
- property.CanWrite
- && !property.IsExplicitlyImplemented()
- && !property.IsStatic()
- && !property.IsIndexer() // first checks that property is assignable in general and not an indexer
- && (withNonPublic || property.GetSetMethodOrNull() != null)
- && (withPrimitive || !property.PropertyType.IsPrimitive(orArrayOfPrimitives: true));
+ bool withNonPublic = false, bool withPrimitive = false)
+ {
+ if (!property.CanWrite || property.IsExplicitlyImplemented())
+ return false;
+
+ if (property.IsStatic())
+ return false;
+
+ return !property.IsIndexer() &&
+ (withNonPublic || property.GetSetMethodOrNull() != null) &&
+ (withPrimitive || !property.PropertyType.IsPrimitive(orArrayOfPrimitives: true));
+ }
/// Returns true if field matches flags provided.
/// Field to match.
@@ -9387,11 +9393,12 @@ public object GetOrTryAdd(int id, object newItem, int disposalOrder)
return item;
_items = _items.AddOrUpdate(id, newItem);
- var disposable = newItem as IDisposable;
- if (disposable != null && disposable != this)
- TrackDisposable(disposable, NextDisposalIndex());
}
+ var disposable = newItem as IDisposable;
+ if (disposable != null && disposable != this)
+ TrackDisposable(disposable, NextDisposalIndex());
+
return newItem;
}
@@ -9400,6 +9407,7 @@ public object GetOrTryAdd(int id, object newItem, int disposalOrder)
new Scope(Parent, Name, _items, _factories, _disposables, _nextDisposalIndex);
///
+ [MethodImpl((MethodImplOptions)256)]
public bool TryGet(out object item, int id)
{
if (_disposed == 1)
@@ -9479,7 +9487,6 @@ public void Dispose()
foreach (var disposable in disposables.Enumerate())
{
// Ignoring disposing exception, as it is not important to proceed the disposal of other items
- // todo: May be it is better to aggregate?
try
{
disposable.Value.Dispose();
@@ -9507,7 +9514,7 @@ public void Dispose()
private int _nextDisposalIndex;
private int _disposed;
- // todo: Improve perf by scaling lockers count with the items amount
+ // todo: Improve performance by scaling lockers count with the items amount
// Sync root is required to create object only once. The same reason as for Lazy.
private readonly object _locker = new object();
@@ -10933,19 +10940,26 @@ public static bool IsPrimitive(this Type type, bool orArrayOfPrimitives = false)
}
/// Returns all public instance constructors for the type
- public static IEnumerable PublicConstructors(this Type type) =>
- type.GetTypeInfo().DeclaredConstructors.Match(c => c.IsPublic && !c.IsStatic);
+ public static IEnumerable PublicConstructors(this Type type)
+ {
+ foreach (var x in type.GetTypeInfo().DeclaredConstructors)
+ if (x.IsPublic && !x.IsStatic)
+ yield return x;
+ }
/// Returns all public instance constructors for the type
- public static IEnumerable PublicAndInternalConstructors(this Type type) =>
- type.GetTypeInfo().DeclaredConstructors.Match(c => !c.IsPrivate && !c.IsStatic);
+ public static IEnumerable PublicAndInternalConstructors(this Type type)
+ {
+ foreach (var x in type.GetTypeInfo().DeclaredConstructors)
+ if (!x.IsPrivate && !x.IsStatic)
+ yield return x;
+ }
/// Enumerates all constructors from input type.
public static IEnumerable Constructors(this Type type,
bool includeNonPublic = false, bool includeStatic = false)
{
var ctors = type.GetTypeInfo().DeclaredConstructors.ToArrayOrSelf();
-
if (ctors.Length == 0)
return ctors;
@@ -10978,34 +10992,31 @@ public static bool IsPrimitive(this Type type, bool orArrayOfPrimitives = false)
!includeNonPublic && !ctor.IsPublic || !includeStatic && ctor.IsStatic;
/// Searches and returns constructor by its signature.
- public static ConstructorInfo GetConstructorOrNull(this Type type,
- bool includeNonPublic = false, params Type[] args)
+ public static ConstructorInfo GetConstructorOrNull(this Type type, bool includeNonPublic = false, params Type[] args)
{
- var pTypesCount = args.Length;
- var ctors = type.GetTypeInfo().DeclaredConstructors.ToArrayOrSelf();
- if (!includeNonPublic)
- ctors = ctors.Match(x => x.IsPublic);
-
- for (var i = 0; i < ctors.Length; i++)
+ var argsLength = args.Length;
+ foreach (var ctor in type.GetTypeInfo().DeclaredConstructors)
{
- var ctor = ctors[i];
- var ps = ctor.GetParameters();
- if (ps.Length != pTypesCount)
- continue;
+ if (includeNonPublic || ctor.IsPublic)
+ {
+ var ctorParams = ctor.GetParameters();
+ if (ctorParams.Length != argsLength)
+ continue;
- if (pTypesCount == 0)
- return ctor;
+ if (argsLength == 0)
+ return ctor;
- var p = 0;
- for (; p < pTypesCount; ++p)
- {
- var paramType = ps[p].ParameterType;
- if (paramType != args[p] && paramType.GetGenericDefinitionOrNull() != args[p])
- break;
- }
+ var i = 0;
+ for (; i < argsLength; ++i)
+ {
+ var paramType = ctorParams[i].ParameterType;
+ if (paramType != args[i] && paramType.GetGenericDefinitionOrNull() != args[i])
+ break;
+ }
- if (p == pTypesCount)
- return ctor;
+ if (i == argsLength)
+ return ctor;
+ }
}
return null;
@@ -11017,23 +11028,35 @@ public static bool IsPrimitive(this Type type, bool orArrayOfPrimitives = false)
/// Searches and returns constructor by its signature, or throws if not found
public static ConstructorInfo Constructor(this Type type, params Type[] args) =>
- type.GetConstructorOrNull(includeNonPublic: true, args: args).ThrowIfNull(
- Error.UnableToFindConstructorWithArgs, type, args);
+ type.GetConstructorOrNull(includeNonPublic: true, args: args).ThrowIfNull(Error.UnableToFindConstructorWithArgs, type, args);
/// Returns single constructor otherwise (if no constructor or more than one) returns null.
- public static ConstructorInfo GetSingleConstructorOrNull(this Type type, bool includeNonPublic = false) =>
- type.Constructors(includeNonPublic).SingleOrDefaultIfMany();
+ public static ConstructorInfo GetSingleConstructorOrNull(this Type type, bool includeNonPublic = false)
+ {
+ ConstructorInfo ctor = null;
+ foreach (var x in type.GetTypeInfo().DeclaredConstructors)
+ {
+ if (ctor != null) // if multiple constructors
+ return null;
+ if (includeNonPublic || x.IsPublic)
+ ctor = x;
+ }
+
+ return ctor;
+ }
/// Returns single constructor otherwise (if no or more than one) throws an exception
public static ConstructorInfo SingleConstructor(this Type type, bool includeNonPublic = false) =>
- type.GetSingleConstructorOrNull(includeNonPublic).ThrowIfNull(
- Error.UnableToFindSingleConstructor, type, includeNonPublic);
+ type.GetSingleConstructorOrNull(includeNonPublic).ThrowIfNull(Error.UnableToFindSingleConstructor, type, includeNonPublic);
/// Looks up for single declared method with the specified name. Returns null if method is not found.
- public static MethodInfo GetSingleMethodOrNull(this Type type, string name, bool includeNonPublic = false) =>
- type.GetTypeInfo().DeclaredMethods
- .Match(m => (includeNonPublic || m.IsPublic) && m.Name == name)
- .SingleOrDefaultIfMany();
+ public static MethodInfo GetSingleMethodOrNull(this Type type, string name, bool includeNonPublic = false)
+ {
+ foreach (var m in type.GetTypeInfo().DeclaredMethods)
+ if ((includeNonPublic || m.IsPublic) && m.Name == name)
+ return m;
+ return null;
+ }
// note: Prefer `GetDeclaredMethod(name)` for supported platforms
/// Looks for single declared (not inherited) method by name, and throws if not found.
@@ -11050,30 +11073,28 @@ public static bool IsPrimitive(this Type type, bool orArrayOfPrimitives = false)
public static MethodInfo GetMethodOrNull(this Type type, string name, params Type[] paramTypes)
{
var pTypesCount = paramTypes.Length;
- var methods = type.GetTypeInfo().DeclaredMethods.ToArrayOrSelf();
- for (var i = 0; i < methods.Length; i++)
+ foreach (var method in type.GetTypeInfo().DeclaredMethods)
{
- var method = methods[i];
if (method.Name != name)
continue;
var ps = method.GetParameters();
- if (ps.Length != pTypesCount)
- continue;
+ if (ps.Length == pTypesCount)
+ {
+ if (pTypesCount == 0)
+ return method;
- if (pTypesCount == 0)
- return method;
+ var p = 0;
+ for (; p < pTypesCount; ++p)
+ {
+ var paramType = ps[p].ParameterType;
+ if (paramType != paramTypes[p] && paramType.GetGenericDefinitionOrNull() != paramTypes[p])
+ break;
+ }
- var p = 0;
- for (; p < pTypesCount; ++p)
- {
- var paramType = ps[p].ParameterType;
- if (paramType != paramTypes[p] && paramType.GetGenericDefinitionOrNull() != paramTypes[p])
- break;
+ if (p == pTypesCount)
+ return method;
}
-
- if (p == pTypesCount)
- return method;
}
return null;
@@ -11081,21 +11102,29 @@ public static MethodInfo GetMethodOrNull(this Type type, string name, params Typ
/// Returns property by name, including inherited. Or null if not found.
public static PropertyInfo Property(this Type type, string name, bool includeBase = false) =>
- type.GetPropertyOrNull(name, includeBase).ThrowIfNull(
- Error.UndefinedPropertyWhenGettingProperty, name, type);
+ type.GetPropertyOrNull(name, includeBase).ThrowIfNull(Error.UndefinedPropertyWhenGettingProperty, name, type);
/// Returns property by name, including inherited. Or null if not found.
- public static PropertyInfo GetPropertyOrNull(this Type type, string name, bool includeBase = false) =>
- type.GetMembers(x => x.DeclaredProperties, includeBase: includeBase).FirstOrDefault(p => p.Name == name);
+ public static PropertyInfo GetPropertyOrNull(this Type type, string name, bool includeBase = false)
+ {
+ foreach (var p in type.GetTypeInfo().DeclaredProperties)
+ if (p.Name == name)
+ return p;
+ return !includeBase ? null : type.GetTypeInfo().BaseType?.GetPropertyOrNull(name, includeBase);
+ }
/// Returns field by name, including inherited. Or null if not found.
public static FieldInfo Field(this Type type, string name, bool includeBase = false) =>
- type.GetFieldOrNull(name, includeBase).ThrowIfNull(
- Error.UndefinedFieldWhenGettingField, name, type);
+ type.GetFieldOrNull(name, includeBase).ThrowIfNull(Error.UndefinedFieldWhenGettingField, name, type);
/// Returns field by name, including inherited. Or null if not found.
- public static FieldInfo GetFieldOrNull(this Type type, string name, bool includeBase = false) =>
- type.GetMembers(x => x.DeclaredFields, includeBase: includeBase).FirstOrDefault(p => p.Name == name);
+ public static FieldInfo GetFieldOrNull(this Type type, string name, bool includeBase = false)
+ {
+ foreach (var f in type.GetTypeInfo().DeclaredFields)
+ if (f.Name == name)
+ return f;
+ return !includeBase ? null : type.GetTypeInfo().BaseType?.GetFieldOrNull(name, includeBase);
+ }
/// Returns type assembly.
public static Assembly GetAssembly(this Type type) => type.GetTypeInfo().Assembly;
@@ -11104,35 +11133,42 @@ public static MethodInfo GetMethodOrNull(this Type type, string name, params Typ
public static bool IsExplicitlyImplemented(this PropertyInfo property) => property.Name.Contains(".");
/// Returns true if member is static, otherwise returns false.
- public static bool IsStatic(this MemberInfo member)
- {
- var method = member as MethodInfo;
- if (method != null)
- return method.IsStatic;
-
- var field = member as FieldInfo;
- if (field != null)
- return field.IsStatic;
-
- var prop = member as PropertyInfo;
- if (prop == null || prop.IsExplicitlyImplemented())
- return false;
-
- var propAccessor =
- prop.GetGetMethodOrNull(includeNonPublic: true) ??
- prop.GetSetMethodOrNull(includeNonPublic: true);
+ public static bool IsStatic(this MemberInfo member) =>
+ member is MethodInfo method ? method.IsStatic
+ : member is FieldInfo field ? field.IsStatic
+ : member is PropertyInfo prop && !prop.IsExplicitlyImplemented() && prop.IsStatic(true);
+
+ /// Find if property is static
+ public static bool IsStatic(this PropertyInfo property, bool includeNonPublic = false)
+ {
+ // e.g.: set_Blah or get_Blah
+ var propName = property.Name;
+ foreach (var m in property.DeclaringType.GetTypeInfo().DeclaredMethods)
+ if (m.IsSpecialName && (includeNonPublic || m.IsPublic))
+ {
+ var name = m.Name;
+ var nameLength = name.Length;
+ if (nameLength > 4 && name[3] == '_' && nameLength - 4 == propName.Length)
+ {
+ var i = 4; ;
+ for (var j = 0; i < nameLength; i++, j++)
+ if (name[i] != propName[j])
+ break;
+ if (i == nameLength)
+ return m.IsStatic;
+ }
+ }
- return propAccessor.IsStatic;
+ return false;
}
/// Return either , or ,
/// .
public static Type GetReturnTypeOrDefault(this MemberInfo member) =>
member is ConstructorInfo ? member.DeclaringType
- : member is MethodInfo ? ((MethodInfo)member).ReturnType
- : member is PropertyInfo ? ((PropertyInfo)member).PropertyType
- : member is FieldInfo ? ((FieldInfo)member).FieldType
- : null;
+ : (member as MethodInfo) ?.ReturnType
+ ?? (member as PropertyInfo)?.PropertyType
+ ?? (member as FieldInfo) ?.FieldType;
/// Returns true if field is backing field for property.
public static bool IsBackingField(this FieldInfo field) =>
@@ -11349,12 +11385,24 @@ public static partial class Portable
internal static IEnumerable ToTypes(IEnumerable x) => x.Select(t => t.AsType());
/// Portable version of PropertyInfo.GetGetMethod.
- public static MethodInfo GetGetMethodOrNull(this PropertyInfo p, bool includeNonPublic = false) =>
- p.DeclaringType.GetSingleMethodOrNull("get_" + p.Name, includeNonPublic);
+ public static MethodInfo GetGetMethodOrNull(this PropertyInfo p, bool includeNonPublic = false)
+ {
+ var name = "get_" + p.Name;
+ foreach (var m in p.DeclaringType.GetTypeInfo().DeclaredMethods)
+ if (m.IsSpecialName && (includeNonPublic || m.IsPublic) && m.Name == name)
+ return m;
+ return null;
+ }
/// Portable version of PropertyInfo.GetSetMethod.
- public static MethodInfo GetSetMethodOrNull(this PropertyInfo p, bool includeNonPublic = false) =>
- p.DeclaringType.GetSingleMethodOrNull("set_" + p.Name, includeNonPublic);
+ public static MethodInfo GetSetMethodOrNull(this PropertyInfo p, bool includeNonPublic = false)
+ {
+ var name = "set_" + p.Name;
+ foreach (var m in p.DeclaringType.GetTypeInfo().DeclaredMethods)
+ if (m.IsSpecialName && (includeNonPublic || m.IsPublic) && m.Name == name)
+ return m;
+ return null;
+ }
private static readonly Lazy> _getEnvCurrentManagedThreadId = Lazy.Of(() =>
{
diff --git a/test/DryIoc.IssuesTests/Issue144_NonPublic_property _as_FactoryMethod_causes_unexplained_NRE.cs b/test/DryIoc.IssuesTests/Issue144_NonPublic_property _as_FactoryMethod_causes_unexplained_NRE.cs
index e7a074f8c..f5b5eaf8f 100644
--- a/test/DryIoc.IssuesTests/Issue144_NonPublic_property _as_FactoryMethod_causes_unexplained_NRE.cs
+++ b/test/DryIoc.IssuesTests/Issue144_NonPublic_property _as_FactoryMethod_causes_unexplained_NRE.cs
@@ -1,10 +1,10 @@
-using System.Reflection;
+using System.Reflection;
using NUnit.Framework;
namespace DryIoc.IssuesTests
{
[TestFixture]
- public class Issue144_NonPublic_property__as_FactoryMethod_causes_unexplained_NRE
+ public class Issue144_NonPublic_property_as_FactoryMethod_causes_unexplained_NRE
{
[Test]
public void There_should_not_be_NRE()