From 13fb3c74b86eea2c9b539456d78bc7f31e4056c2 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Sun, 21 Oct 2018 14:12:29 +0300 Subject: [PATCH] #164 add working metadata caching --- Spring.Net.sln.DotSettings | 1 + .../Aspects/ConsoleLoggingThrowsAdvice.cs | 8 +- .../Aspects/ConsoleLoggingAdvice.cs | 6 - .../ModificationAdvice.cs | 33 +- .../src/Spring.AopQuickStart.Step7/Program.cs | 8 +- .../TxQuickStart/AccountManagerTests.cs | 6 - .../AbstractAdvisorAutoProxyCreator.cs | 33 +- .../DefaultAdvisorAutoProxyCreator.cs | 11 +- .../AutoProxy/IAdvisorRetrievalHelper.cs | 2 +- .../InheritanceBasedAopConfigurer.cs | 4 +- .../ObjectFactoryAdvisorRetrievalHelper.cs | 2 +- .../Aop/Framework/ProxyFactoryObject.cs | 19 +- .../ConfigurationClassPostProcessor.cs | 2 +- .../Support/AbstractApplicationContext.cs | 77 +-- .../Spring.Core/Core/CriteriaMemberFilter.cs | 14 +- .../Spring.Core/Core/OrderComparator.cs | 17 +- .../Processors/OrderByProcessor.cs | 2 +- .../AutowiredAttributeObjectPostProcessor.cs | 322 +++++++------ .../Factory/Attributes/InjectionMetadata.cs | 157 +++---- .../IConfigurableListableObjectFactory.cs | 42 +- .../Config/IConfigurableObjectFactory.cs | 6 +- .../IInstantiationAwareObjectPostProcessor.cs | 2 +- .../Factory/Config/ObjectDefinitionHolder.cs | 55 +-- .../Config/PropertyPlaceholderConfigurer.cs | 4 +- .../Config/VariablePlaceholderConfigurer.cs | 30 +- .../Objects/Factory/IListableObjectFactory.cs | 91 ++-- .../Objects/Factory/IObjectFactory.cs | 30 +- .../Objects/Factory/ObjectFactoryUtils.cs | 20 +- .../AbstractAutowireCapableObjectFactory.cs | 46 +- .../Factory/Support/AbstractObjectFactory.cs | 258 +++++++---- .../Objects/Factory/Support/AutowireUtils.cs | 31 +- .../Factory/Support/ConstructorResolver.cs | 28 +- .../Support/DefaultListableObjectFactory.cs | 438 ++++++++++++------ .../Support/IObjectDefinitionRegistry.cs | 30 +- .../Objects/Factory/Support/Interface1.cs | 61 +++ .../Factory/Support/LookupMethodOverride.cs | 2 +- .../MethodInjectingInstantiationStrategy.cs | 2 +- .../Support/ObjectDefinitionReaderUtils.cs | 2 +- .../Support/ObjectDefinitionValueResolver.cs | 13 +- .../Support/StaticListableObjectFactory.cs | 49 +- .../DefaultObjectDefinitionDocumentReader.cs | 219 ++++----- .../Xml/ObjectDefinitionParserHelper.cs | 6 +- .../Factory/Xml/ReplacedMethodOverride.cs | 2 +- .../Objects/Support/PropertyComparator.cs | 2 +- .../Spring.Core/Util/CollectionUtils.cs | 12 - src/Spring/Spring.Core/Util/ObjectUtils.cs | 7 +- .../NHibernate/Bytecode/ObjectsFactory.cs | 6 +- .../Bytecode/ReflectionOptimizer.cs | 4 +- .../Data/NHibernate/SessionFactoryUtils.cs | 4 +- .../Data/Common/DbProviderFactory.cs | 7 +- .../Core/DefaultMessageQueueFactory.cs | 4 +- .../Core/MessageQueueMetadataCache.cs | 2 +- .../Xml/WebObjectDefinitionParserHelper.cs | 38 +- .../Spring.Web/Web/Support/ContextMonitor.cs | 10 +- .../AutoProxy/AdvisorAutoProxyCreatorTests.cs | 2 +- ...ributeConfigObjectDefinitionParserTests.cs | 1 + ...omponentScanObjectDefinitionParserTests.cs | 1 + .../Support/ApplicationObjectSupportTests.cs | 119 +---- .../AbstractListableObjectFactoryTests.cs | 80 ++-- .../DefaultListableObjectFactoryPerfTests.cs | 2 +- .../DefaultListableObjectFactoryTests.cs | 85 ++-- .../Factory/ObjectFactoryUtilsTests.cs | 7 +- ...oryUtils_PreserveOrderInHierarchy_Tests.cs | 6 +- .../ObjectDefinitionReaderUtilsTests.cs | 2 +- .../Factory/Xml/XmlObjectCollectionTests.cs | 9 +- .../Factory/Xml/XmlObjectFactoryTests.cs | 4 +- .../Validation/HelperClasses.cs | 46 +- .../Data/Common/DbProviderFactoryTests.cs | 2 +- .../Nms/Config/NmsNamespaceHandlerTests.cs | 6 +- ...annelFactoryObjectDefinitionParserTests.cs | 2 +- 70 files changed, 1405 insertions(+), 1256 deletions(-) create mode 100644 src/Spring/Spring.Core/Objects/Factory/Support/Interface1.cs diff --git a/Spring.Net.sln.DotSettings b/Spring.Net.sln.DotSettings index 375aca96..0ad92593 100644 --- a/Spring.Net.sln.DotSettings +++ b/Spring.Net.sln.DotSettings @@ -3,6 +3,7 @@ Required Required Required + False License /* * Copyright 2018 the original author or authors. diff --git a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Common/Aspects/ConsoleLoggingThrowsAdvice.cs b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Common/Aspects/ConsoleLoggingThrowsAdvice.cs index 74055284..93ca8444 100644 --- a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Common/Aspects/ConsoleLoggingThrowsAdvice.cs +++ b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Common/Aspects/ConsoleLoggingThrowsAdvice.cs @@ -18,15 +18,10 @@ #endregion -#region Imports - using System; -using System.Reflection; using Spring.Aop; -#endregion - namespace Spring.AopQuickStart.Aspects { /// @@ -39,8 +34,7 @@ namespace Spring.AopQuickStart.Aspects { public void AfterThrowing(Exception ex) { - Console.Error.WriteLine( - String.Format("Advised method threw this exception : {0}", ex.Message)); + Console.Error.WriteLine($"Advised method threw this exception : {ex.Message}"); } } } \ No newline at end of file diff --git a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step4/Aspects/ConsoleLoggingAdvice.cs b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step4/Aspects/ConsoleLoggingAdvice.cs index 5c7401b1..20d8cd2b 100644 --- a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step4/Aspects/ConsoleLoggingAdvice.cs +++ b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step4/Aspects/ConsoleLoggingAdvice.cs @@ -18,16 +18,10 @@ #endregion -#region Imports - using System; using AopAlliance.Intercept; -using Spring.AopQuickStart.Attributes; - -#endregion - namespace Spring.AopQuickStart.Aspects { /// diff --git a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step6/ModificationAdvice.cs b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step6/ModificationAdvice.cs index 2a89f9f1..8b7460d9 100644 --- a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step6/ModificationAdvice.cs +++ b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step6/ModificationAdvice.cs @@ -1,29 +1,27 @@ -using System; using System.Reflection; using AopAlliance.Intercept; -using Spring.Aop.Framework; namespace Spring.AopQuickStart { public class ModificationAdvice : IMethodInterceptor { - public virtual Object Invoke(IMethodInvocation invocation) + public virtual object Invoke(IMethodInvocation invocation) { MethodInfo method = invocation.Method; object proxy = invocation.Proxy; - if (proxy is IIsModified) + if (proxy is IIsModified obj) { - IIsModified obj = (IIsModified) proxy; if (IsSetter(method)) { obj.IsModified = HasModificationOccured(method, invocation.This, invocation.Arguments); } } + return invocation.Proceed(); } - private bool HasModificationOccured(MethodInfo setter, Object target, Object[] args) + private bool HasModificationOccured(MethodInfo setter, object target, object[] args) { PropertyInfo property = target.GetType().GetProperty(setter.Name.Substring(4)); @@ -31,25 +29,25 @@ namespace Spring.AopQuickStart { // modification check is unimportant // for write only methods - Object newVal = args[0]; - Object oldVal = property.GetValue(target, null); + object newVal = args[0]; + object oldVal = property.GetValue(target, null); - if ((newVal == null) && (oldVal == null)) + if (newVal == null && (oldVal == null)) { return false; } - else if ((newVal == null) && (oldVal != null)) + + if (newVal == null && (oldVal != null)) { return true; } - else if ((newVal != null) && (oldVal == null)) + + if ((oldVal == null)) { return true; } - else - { - return (!newVal.Equals(oldVal)); - } + + return (!newVal.Equals(oldVal)); } return false; @@ -57,8 +55,7 @@ namespace Spring.AopQuickStart private bool IsSetter(MethodInfo method) { - return (method.Name.StartsWith("set_")) && (method.GetParameters().Length == 1); + return method.Name.StartsWith("set_") && method.GetParameters().Length == 1; } - } -} +} \ No newline at end of file diff --git a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step7/Program.cs b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step7/Program.cs index be74d10c..396528af 100644 --- a/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step7/Program.cs +++ b/examples/Spring/Spring.AopQuickStart/src/Spring.AopQuickStart.Step7/Program.cs @@ -18,18 +18,12 @@ #endregion -#region Imports - using System; -using System.Collections.Generic; - using Spring.Context; using Spring.Context.Support; using Spring.AopQuickStart.Commands; -#endregion - namespace Spring.AopQuickStart { /// @@ -47,7 +41,7 @@ namespace Spring.AopQuickStart { // Create AOP proxy using Spring.NET IoC container. IApplicationContext ctx = ContextRegistry.GetContext(); - IDictionary commands = ctx.GetObjects(); + var commands = ctx.GetObjects(); foreach (ICommand command in commands.Values) { diff --git a/examples/Spring/Spring.TxQuickStart/test/Spring/Spring.TxQuickStart.Tests/TxQuickStart/AccountManagerTests.cs b/examples/Spring/Spring.TxQuickStart/test/Spring/Spring.TxQuickStart.Tests/TxQuickStart/AccountManagerTests.cs index ff480e28..502d2725 100644 --- a/examples/Spring/Spring.TxQuickStart/test/Spring/Spring.TxQuickStart.Tests/TxQuickStart/AccountManagerTests.cs +++ b/examples/Spring/Spring.TxQuickStart/test/Spring/Spring.TxQuickStart.Tests/TxQuickStart/AccountManagerTests.cs @@ -18,10 +18,7 @@ #endregion -#region Imports - using System; -using System.Collections.Generic; using System.Data; using NUnit.Framework; using Spring.Aop.Config; @@ -34,8 +31,6 @@ using Spring.Objects.Factory.Xml; using Spring.Transaction.Config; using Spring.TxQuickStart.Services; -#endregion - namespace Spring.TxQuickStart { [TestFixture] @@ -54,7 +49,6 @@ namespace Spring.TxQuickStart NamespaceParserRegistry.RegisterParser(typeof(TxNamespaceParser)); NamespaceParserRegistry.RegisterParser(typeof(AopNamespaceParser)); IApplicationContext context = CreateContextFromXml(); - IDictionary dict = context.GetObjects(); accountManager = context["accountManager"] as IAccountManager; CleanDb(context); } diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs index c670707a..d4431331 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright � 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -153,11 +153,11 @@ namespace Spring.Aop.Framework.AutoProxy /// protected IList FindEligibleAdvisors(Type targetType, string targetName) { - IList candidateAdvisors = FindCandidateAdvisors(targetType, targetName); - IList eligibleAdvisors = FindAdvisorsThatCanApply(candidateAdvisors, targetType, targetName); + List candidateAdvisors = FindCandidateAdvisors(targetType, targetName); + List eligibleAdvisors = FindAdvisorsThatCanApply(candidateAdvisors, targetType, targetName); ExtendAdvisors(eligibleAdvisors, targetType, targetName); - eligibleAdvisors = SortAdvisors(eligibleAdvisors); + SortAdvisors(eligibleAdvisors); return eligibleAdvisors; } @@ -168,7 +168,7 @@ namespace Spring.Aop.Framework.AutoProxy /// the type of the object to be advised /// the name of the object to be advised /// the list of candidate advisors - protected virtual IList FindCandidateAdvisors(Type targetType, string targetName) + protected virtual List FindCandidateAdvisors(Type targetType, string targetName) { return _advisorRetrievalHelper.FindAdvisorObjects(targetType, targetName); } @@ -181,7 +181,7 @@ namespace Spring.Aop.Framework.AutoProxy /// the target object's type /// the target object's name /// the list of applicable advisors - protected virtual IList FindAdvisorsThatCanApply(IList candidateAdvisors, Type targetType, string targetName) + protected virtual List FindAdvisorsThatCanApply(List candidateAdvisors, Type targetType, string targetName) { if (candidateAdvisors.Count==0) { @@ -195,7 +195,7 @@ namespace Spring.Aop.Framework.AutoProxy { if (logger.IsInfoEnabled) { - logger.Info(string.Format("Candidate advisor [{0}] accepted for targetType [{1}]", candidate, targetType)); + logger.Info($"Candidate advisor [{candidate}] accepted for targetType [{targetType}]"); } eligibleAdvisors.Add(candidate); } @@ -210,7 +210,7 @@ namespace Spring.Aop.Framework.AutoProxy { if (logger.IsInfoEnabled) { - logger.Info(string.Format("Candidate advisor [{0}] accepted for targetType [{1}]", candidate, targetType)); + logger.Info($"Candidate advisor [{candidate}] accepted for targetType [{targetType}]"); } eligibleAdvisors.Add(candidate); } @@ -218,7 +218,7 @@ namespace Spring.Aop.Framework.AutoProxy { if (logger.IsInfoEnabled) { - logger.Info(string.Format("Candidate advisor [{0}] rejected for targetType [{1}]", candidate, targetType)); + logger.Info($"Candidate advisor [{candidate}] rejected for targetType [{targetType}]"); } } } @@ -231,20 +231,9 @@ namespace Spring.Aop.Framework.AutoProxy /// /// The advisors. /// - protected virtual IList SortAdvisors(IList advisors) + protected virtual void SortAdvisors(List advisors) { - if (advisors.Count==0) - { - return advisors; - } - - if (advisors is List) - ((List)advisors).Sort(new OrderComparator()); - else if (advisors is ArrayList) - ((ArrayList) advisors).Sort(new OrderComparator()); - else if (advisors is Array) - Array.Sort((Array) advisors, new OrderComparator()); - return advisors; + advisors.Sort(OrderComparator.Instance); } /// diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs index ef8d20e8..2816073c 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright � 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,10 +41,11 @@ namespace Spring.Aop.Framework.AutoProxy /// /// Separator between prefix and remainder of object name /// - public static readonly string SEPARATOR = "."; + public const string Separator = "."; + private bool usePrefix; private string advisorObjectNamePrefix; - private IList cachedAdvisors; + private List cachedAdvisors; #region Properties @@ -94,7 +95,7 @@ namespace Spring.Aop.Framework.AutoProxy // If no infrastructure object name prefix has been set, override it. if (advisorObjectNamePrefix == null) { - advisorObjectNamePrefix = value + SEPARATOR; + advisorObjectNamePrefix = value + Separator; } } } @@ -107,7 +108,7 @@ namespace Spring.Aop.Framework.AutoProxy /// the type of the object to be advised /// the name of the object to be advised /// the list of candidate advisors - protected override IList FindCandidateAdvisors(Type targetType, string targetName) + protected override List FindCandidateAdvisors(Type targetType, string targetName) { if (cachedAdvisors == null) { cachedAdvisors = base.FindCandidateAdvisors(targetType, targetName); diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/IAdvisorRetrievalHelper.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/IAdvisorRetrievalHelper.cs index 62722976..80bc0237 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/IAdvisorRetrievalHelper.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/IAdvisorRetrievalHelper.cs @@ -13,6 +13,6 @@ namespace Spring.Aop.Framework.AutoProxy /// /// Get the list of advisor objects to apply on the target. /// - IList FindAdvisorObjects(Type targetType, string targetName); + List FindAdvisorObjects(Type targetType, string targetName); } } \ No newline at end of file diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs index 6c875b3f..787835e0 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/InheritanceBasedAopConfigurer.cs @@ -1,5 +1,5 @@ /* - * Copyright © 2002-2011 the original author or authors. + * Copyright � 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -155,7 +155,7 @@ namespace Spring.Aop.Framework.AutoProxy /// public void PostProcessObjectFactory(IConfigurableListableObjectFactory factory) { - IList objectDefinitionNames = factory.GetObjectDefinitionNames(); + var objectDefinitionNames = factory.GetObjectDefinitionNames(); for (int i = 0; i < objectDefinitionNames.Count; ++i) { string name = objectDefinitionNames[i]; diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectFactoryAdvisorRetrievalHelper.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectFactoryAdvisorRetrievalHelper.cs index 71196265..20cff858 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectFactoryAdvisorRetrievalHelper.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectFactoryAdvisorRetrievalHelper.cs @@ -63,7 +63,7 @@ namespace Spring.Aop.Framework.AutoProxy /// the type of the object to be advised /// the name of the object to be advised /// A list of eligible instances - public virtual IList FindAdvisorObjects(Type targetType, string targetName) + public virtual List FindAdvisorObjects(Type targetType, string targetName) { IList advisorNames = GetAdvisorCandidateNames(targetType, targetName); diff --git a/src/Spring/Spring.Aop/Aop/Framework/ProxyFactoryObject.cs b/src/Spring/Spring.Aop/Aop/Framework/ProxyFactoryObject.cs index 5a49785b..7686b53e 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/ProxyFactoryObject.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/ProxyFactoryObject.cs @@ -15,7 +15,6 @@ */ using System; -using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; @@ -606,15 +605,15 @@ namespace Spring.Aop.Framework /// Add all global interceptors and pointcuts. private void AddGlobalAdvisor(IListableObjectFactory objectFactory, string prefix) { - IList globalAspectNames = + var globalAspectNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(objectFactory, typeof(IAdvisors)); - IList globalAdvisorNames = + var globalAdvisorNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(objectFactory, typeof(IAdvisor)); - IList globalInterceptorNames = + var globalInterceptorNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(objectFactory, typeof(IInterceptor)); + List objects = new List(); Dictionary names = new Dictionary(); - for (int i = 0; i < globalAspectNames.Count; i++) { string name = globalAspectNames[i]; @@ -656,7 +655,7 @@ namespace Spring.Aop.Framework names[obj] = name; } } - objects.Sort(new OrderComparator()); + objects.Sort(OrderComparator.Instance); foreach (object obj in objects) { string name = names[obj]; @@ -716,11 +715,11 @@ namespace Spring.Aop.Framework /// Add all global introductions. private void AddGlobalIntroduction(IListableObjectFactory objectFactory, string prefix) { - IList globalAspectNames = + var globalAspectNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(objectFactory, typeof(IAdvisors)); - IList globalAdvisorNames = + var globalAdvisorNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(objectFactory, typeof(IAdvisor)); - IList globalIntroductionNames = + var globalIntroductionNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(objectFactory, typeof(IAdvice)); List objects = new List(); Dictionary names = new Dictionary(); @@ -770,7 +769,7 @@ namespace Spring.Aop.Framework } } } - objects.Sort(new OrderComparator()); + objects.Sort(OrderComparator.Instance); for (var i = 0; i < objects.Count; i++) { object obj = objects[i]; diff --git a/src/Spring/Spring.Core/Context/Attributes/ConfigurationClassPostProcessor.cs b/src/Spring/Spring.Core/Context/Attributes/ConfigurationClassPostProcessor.cs index f907fa14..934fef32 100644 --- a/src/Spring/Spring.Core/Context/Attributes/ConfigurationClassPostProcessor.cs +++ b/src/Spring/Spring.Core/Context/Attributes/ConfigurationClassPostProcessor.cs @@ -117,7 +117,7 @@ namespace Spring.Context.Attributes { ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(objectFactory); - IList objectNames = objectFactory.GetObjectDefinitionNames(); + var objectNames = objectFactory.GetObjectDefinitionNames(); foreach (string name in objectNames) { diff --git a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs index 50acba73..36863b57 100644 --- a/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs +++ b/src/Spring/Spring.Core/Context/Support/AbstractApplicationContext.cs @@ -497,13 +497,13 @@ namespace Spring.Context.Support } } - IDictionary objectMap = objectFactory.GetObjects(true, false); + var objectMap = objectFactory.GetObjects(true, false); List registryPostProcessorObjects = null; if (objectMap.Count > 0) { registryPostProcessorObjects = new List(objectMap.Values); - registryPostProcessorObjects.Sort(new OrderComparator()); + registryPostProcessorObjects.Sort(OrderComparator.Instance); foreach (var processor in registryPostProcessorObjects) { processor.PostProcessObjectDefinitionRegistry(registry); @@ -535,7 +535,7 @@ namespace Spring.Context.Support // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! - IList factoryProcessorNames = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false); + var factoryProcessorNames = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false); // Separate between ObjectFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. @@ -573,7 +573,7 @@ namespace Spring.Context.Support { orderedFactoryProcessors.Add(SafeGetObjectFactory().GetObject(orderedFactoryProcessorsName)); } - orderedFactoryProcessors.Sort(new OrderComparator()); + orderedFactoryProcessors.Sort(OrderComparator.Instance); InvokeObjectFactoryPostProcessors(orderedFactoryProcessors, SafeGetObjectFactory()); // and then the unordered ones... @@ -595,19 +595,21 @@ namespace Spring.Context.Support } protected virtual void InvokePriorityOrderedObjectFactoryPostProcessors( - IList factoryProcessorNames, + IReadOnlyList factoryProcessorNames, List priorityOrderedFactoryProcessors) { - priorityOrderedFactoryProcessors.Sort(new OrderComparator()); + priorityOrderedFactoryProcessors.Sort(OrderComparator.Instance); InvokeObjectFactoryPostProcessors(priorityOrderedFactoryProcessors, SafeGetObjectFactory()); + var processorNames = factoryProcessorNames.Count > 0 ? new HashSet(factoryProcessorNames) : null; + // Now will find any additional IObjectFactoryPostProcessors that implement IPriorityOrdered that may have been // resolved due to using TypeAlias - IList factoryProcessorNamesAfterTypeAlias = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false); + var factoryProcessorNamesAfterTypeAlias = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false); priorityOrderedFactoryProcessors.Clear(); foreach (string factoryProcessorName in factoryProcessorNamesAfterTypeAlias) { - if (!factoryProcessorNames.Contains(factoryProcessorName)) + if (processorNames == null || !processorNames.Contains(factoryProcessorName)) { if (IsTypeMatch(factoryProcessorName, typeof(IPriorityOrdered))) { @@ -616,7 +618,7 @@ namespace Spring.Context.Support } } // Second, invoke newly discovered IObjectFactoryPostProcessors that implement IPriorityOrdered. - priorityOrderedFactoryProcessors.Sort(new OrderComparator()); + priorityOrderedFactoryProcessors.Sort(OrderComparator.Instance); InvokeObjectFactoryPostProcessors(priorityOrderedFactoryProcessors, SafeGetObjectFactory()); } @@ -637,21 +639,20 @@ namespace Spring.Context.Support private void RegisterObjectPostProcessors(IConfigurableListableObjectFactory objectFactory) { RefreshObjectPostProcessorChecker(objectFactory); - IDictionary dict = GetObjects(true, false); + var dict = GetObjects(true, false); List objectProcessors = new List(dict.Values); + // objectProcessors.Sort(new OrderComparator()); - foreach (IObjectPostProcessor objectPostProcessor in objectProcessors) + for (var i = 0; i < objectProcessors.Count; i++) { + IObjectPostProcessor objectPostProcessor = objectProcessors[i]; SafeGetObjectFactory().AddObjectPostProcessor(objectPostProcessor); } if (log.IsDebugEnabled) { - log.Debug(string.Format( - CultureInfo.InvariantCulture, - "processed {0} IObjectPostProcessors defined in application context [{1}].", - objectProcessors.Count, - Name)); + log.Debug( + $"processed {objectProcessors.Count} IObjectPostProcessors defined in application context [{Name}]."); } } @@ -704,12 +705,11 @@ namespace Spring.Context.Support if (log.IsDebugEnabled) { - log.Debug(string.Format( - "No IEventRegistry found with name '{0}' : using default '{1}'.", - EventRegistryObjectName, EventRegistry)); + log.Debug( + $"No IEventRegistry found with name '{EventRegistryObjectName}' : using default '{EventRegistry}'."); } } - ICollection interestedParties = GetObjects(true, false).Values; + var interestedParties = GetObjects(true, false).Values; foreach (IEventRegistryAware party in interestedParties) { party.EventRegistry = EventRegistry; @@ -816,7 +816,7 @@ namespace Spring.Context.Support private void RefreshApplicationEventListeners() { - ICollection listeners = GetObjects(true, false).Values; + var listeners = GetObjects(true, false).Values; foreach (IApplicationEventListener applicationListener in listeners) { EventRegistry.Subscribe(applicationListener); @@ -1125,7 +1125,7 @@ namespace Spring.Context.Support /// are defined. /// /// - public IList GetObjectNamesForType(Type type) + public IReadOnlyList GetObjectNamesForType(Type type) { return SafeGetObjectFactory().GetObjectNamesForType(type); } @@ -1153,7 +1153,7 @@ namespace Spring.Context.Support /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectNames() + public IReadOnlyList GetObjectNames() { return GetObjectNamesForType(typeof(T)); } @@ -1179,7 +1179,7 @@ namespace Spring.Context.Support /// are defined. /// /// - public IList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) { return SafeGetObjectFactory().GetObjectNamesForType(type, includePrototypes, includeFactoryObjects); } @@ -1208,18 +1208,18 @@ namespace Spring.Context.Support /// for all object names. /// /// - /// Whether to include prototype objects too or just singletons (also applies to - /// s). + /// Whether to include prototype objects too or just singletons (also applies to + /// s). /// /// - /// Whether to include s too - /// or just normal objects. + /// Whether to include s too + /// or just normal objects. /// /// /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) { return GetObjectNamesForType(typeof(T), includePrototypes, includeFactoryObjects); } @@ -1232,7 +1232,7 @@ namespace Spring.Context.Support /// are defined. /// /// - public IList GetObjectDefinitionNames() + public IReadOnlyList GetObjectDefinitionNames() { return GetObjectDefinitionNames(false); } @@ -1246,7 +1246,7 @@ namespace Spring.Context.Support /// The names of all objects defined in this factory, if includeAncestors is true includes all /// objects defined in parent factories, or an empty array if none are defined. /// - public IList GetObjectDefinitionNames(bool includeAncestors) + public IReadOnlyList GetObjectDefinitionNames(bool includeAncestors) { return SafeGetObjectFactory().GetObjectDefinitionNames(includeAncestors); } @@ -1316,7 +1316,7 @@ namespace Spring.Context.Support /// If the objects could not be created. /// /// - public IDictionary GetObjectsOfType(Type type) + public IReadOnlyDictionary GetObjectsOfType(Type type) { return GetObjectsOfType(type, true, true); } @@ -1348,7 +1348,7 @@ namespace Spring.Context.Support /// /// If the objects could not be created. /// - public IDictionary GetObjects() + public IReadOnlyDictionary GetObjects() { return SafeGetObjectFactory().GetObjects(true, true); } @@ -1380,7 +1380,7 @@ namespace Spring.Context.Support /// If the objects could not be created. /// /// - public IDictionary GetObjectsOfType( + public IReadOnlyDictionary GetObjectsOfType( Type type, bool includePrototypes, bool includeFactoryObjects) { return SafeGetObjectFactory().GetObjectsOfType(type, includePrototypes, includeFactoryObjects); @@ -1412,7 +1412,7 @@ namespace Spring.Context.Support /// /// If the objects could not be created. /// - public IDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) { return SafeGetObjectFactory().GetObjects(includePrototypes, includeFactoryObjects); } @@ -1448,7 +1448,7 @@ namespace Spring.Context.Support /// public T GetObject() { - IList objectNamesForType = GetObjectNamesForType(typeof(T)); + var objectNamesForType = GetObjectNamesForType(typeof(T)); if ((objectNamesForType == null) || (objectNamesForType.Count == 0)) { throw new NoSuchObjectDefinitionException(typeof(T).FullName, "Requested Type not Defined in the Context."); @@ -1456,7 +1456,8 @@ namespace Spring.Context.Support if (objectNamesForType.Count > 1) { - throw new ObjectDefinitionStoreException(string.Format("More than one definition for {0} found in the Context.", typeof(T).FullName)); + throw new ObjectDefinitionStoreException( + $"More than one definition for {typeof(T).FullName} found in the Context."); } return (T)GetObject(objectNamesForType[0]); @@ -1520,7 +1521,7 @@ namespace Spring.Context.Support /// If there's no such object definition. /// /// - public IList GetAliases(string name) + public IReadOnlyList GetAliases(string name) { return SafeGetObjectFactory().GetAliases(name); } diff --git a/src/Spring/Spring.Core/Core/CriteriaMemberFilter.cs b/src/Spring/Spring.Core/Core/CriteriaMemberFilter.cs index 73ba0332..122fcd47 100644 --- a/src/Spring/Spring.Core/Core/CriteriaMemberFilter.cs +++ b/src/Spring/Spring.Core/Core/CriteriaMemberFilter.cs @@ -1,7 +1,5 @@ -#region License - /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +14,8 @@ * limitations under the License. */ -#endregion - -#region Imports - using System.Reflection; -#endregion - namespace Spring.Core { /// @@ -39,7 +31,6 @@ namespace Spring.Core /// Rick Evans public class CriteriaMemberFilter { - #region Constructor (s) / Destructor /// /// Creates a new instance of the /// class. @@ -47,9 +38,7 @@ namespace Spring.Core public CriteriaMemberFilter () { } - #endregion - #region Methods /// /// Returns true if the supplied instance /// satisfies the supplied (which must be an @@ -75,6 +64,5 @@ namespace Spring.Core ICriteria criteria = filterCriteria as ICriteria; return criteria.IsSatisfied (member); } - #endregion } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Core/OrderComparator.cs b/src/Spring/Spring.Core/Core/OrderComparator.cs index fce0212b..57231165 100644 --- a/src/Spring/Spring.Core/Core/OrderComparator.cs +++ b/src/Spring/Spring.Core/Core/OrderComparator.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,6 +62,8 @@ namespace Spring.Core [Serializable] public class OrderComparator : IComparer { + public static readonly IComparer Instance = new OrderComparator(); + /// /// Compares two objects and returns a value indicating whether one is less than, /// equal to or greater than the other. @@ -81,20 +83,19 @@ namespace Spring.Core { IOrdered o1lhs = o1 as IOrdered; IOrdered o2rhs = o2 as IOrdered; - int lhs = o1lhs != null ? o1lhs.Order : Int32.MaxValue; - int rhs = o2rhs != null ? o2rhs.Order : Int32.MaxValue; + int lhs = o1lhs?.Order ?? int.MaxValue; + int rhs = o2rhs?.Order ?? int.MaxValue; if (lhs < rhs) { return - 1; } - else if (lhs > rhs) + + if (lhs > rhs) { return 1; } - else - { - return CompareEqualOrder(o1, o2); - } + + return CompareEqualOrder(o1, o2); } /// diff --git a/src/Spring/Spring.Core/Expressions/Processors/OrderByProcessor.cs b/src/Spring/Spring.Core/Expressions/Processors/OrderByProcessor.cs index 70eee788..51f65038 100644 --- a/src/Spring/Spring.Core/Expressions/Processors/OrderByProcessor.cs +++ b/src/Spring/Spring.Core/Expressions/Processors/OrderByProcessor.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs index 75f3a805..38a38ab9 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/AutowiredAttributeObjectPostProcessor.cs @@ -31,6 +31,7 @@ using Spring.Objects.Factory.Config; using Common.Logging; using Spring.Objects.Factory.Support; +using Spring.Util; namespace Spring.Objects.Factory.Attributes { @@ -66,19 +67,20 @@ namespace Spring.Objects.Factory.Attributes /// thus the latter configuration will override the former for properties wired through /// both approaches. /// - public class AutowiredAttributeObjectPostProcessor : InstantiationAwareObjectPostProcessorAdapter, IObjectFactoryAware, IOrdered + public class AutowiredAttributeObjectPostProcessor + : InstantiationAwareObjectPostProcessorAdapter, IMergedObjectDefinitionPostProcessor, IObjectFactoryAware, IOrdered { private static readonly ILog logger = LogManager.GetLogger(); - private int order = int.MaxValue - 2; + private IConfigurableListableObjectFactory objectFactory; - private static IConfigurableListableObjectFactory objectFactory; + private readonly HashSet lookupMethodsChecked = new HashSet(); private readonly SynchronizedHashtable candidateConstructorsCache = new SynchronizedHashtable(); - private readonly IDictionary injectionMetadataCache = new Dictionary(); + private readonly Dictionary injectionMetadataCache = new Dictionary(); - private readonly IList autowiredPropertyTypes = new List(); + private readonly List autowiredPropertyTypes = new List(); /// /// Return the order value of this object, where a higher value means greater in @@ -95,11 +97,7 @@ namespace Spring.Objects.Factory.Attributes /// /// The order value. /// - public int Order - { - get { return order; } - private set { order = value; } - } + public int Order { get; private set; } = int.MaxValue - 2; /// /// Callback that supplies the owning factory to an object instance. @@ -120,7 +118,19 @@ namespace Spring.Objects.Factory.Attributes /// public IObjectFactory ObjectFactory { - set { objectFactory = (IConfigurableListableObjectFactory) value; } + set => objectFactory = (IConfigurableListableObjectFactory) value; + } + + public void PostProcessMergedObjectDefinition(RootObjectDefinition objectDefinition, Type objectType, string objectName) + { + var metadata = FindAutowiringMetadata(objectName, objectType, null); + metadata.CheckConfigMembers(objectDefinition); + } + + public void ResetObjectDefinition(string beanName) + { + this.lookupMethodsChecked.Remove(beanName); + injectionMetadataCache.Remove(beanName); } /// @@ -154,6 +164,40 @@ namespace Spring.Objects.Factory.Attributes /// in case of errors public override ConstructorInfo[] DetermineCandidateConstructors(Type objectType, string objectName) { + /* TODO implement Lookup + // Let's check for lookup methods here.. + if (!lookupMethodsChecked.Contains(objectName)) + { + try + { + foreach (var method in objectType.GetMethods()) + { + ValueAttribute lookup = method.GetCustomAttribute(true); + if (lookup != null) + { + AssertUtils.State(objectFactory != null, "No ObjectFactory available"); + var lookupMethodOverride = new LookupMethodOverride(method.Name, lookup.Expression); + try + { + var mbd = (RootObjectDefinition) objectFactory.GetMergedObjectDefinition(objectName); + mbd.MethodOverrides.Add(lookupMethodOverride); + } + catch (NoSuchObjectDefinitionException) + { + throw new ObjectCreationException(objectName, + "Cannot apply @Lookup to objects without corresponding object definition"); + } + } + }; + } + catch (Exception ex) + { + throw new ObjectCreationException(objectName, "Lookup method resolution failed", ex); + } + + lookupMethodsChecked.Add(objectName); + }*/ + // Quick check on the concurrent map first, with minimal locking. ConstructorInfo[] candidateConstructors = candidateConstructorsCache.ContainsKey(objectType) ? (ConstructorInfo[]) candidateConstructorsCache[objectType] @@ -173,9 +217,7 @@ namespace Spring.Objects.Factory.Attributes ConstructorInfo defaultConstructor = null; foreach (var candidate in rawCandidates) { - AutowiredAttribute attr = - Attribute.GetCustomAttribute(candidate, typeof (AutowiredAttribute)) as AutowiredAttribute; - if (attr != null) + if (Attribute.GetCustomAttribute(candidate, typeof (AutowiredAttribute)) is AutowiredAttribute attr) { if (requiredConstructor != null) { @@ -249,7 +291,7 @@ namespace Spring.Objects.Factory.Attributes var objectDefinition = objectFactory.GetObjectDefinition(objectName) as RootObjectDefinition; if (objectType != null) { - var metadata = FindAutowiringMetadata(objectType); + var metadata = FindAutowiringMetadata(objectName, objectType, null); metadata.CheckConfigMembers(objectDefinition); } return null; @@ -267,7 +309,7 @@ namespace Spring.Objects.Factory.Attributes public override IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, IList pis, object objectInstance, string objectName) { - var metadata = FindAutowiringMetadata(objectInstance.GetType()); + var metadata = FindAutowiringMetadata(objectName, objectInstance.GetType(), pvs); try { metadata.Inject(objectInstance, objectName, pvs); @@ -279,22 +321,25 @@ namespace Spring.Objects.Factory.Attributes return pvs; } - private InjectionMetadata FindAutowiringMetadata(Type objectType) + private InjectionMetadata FindAutowiringMetadata(string objectName, Type objectType, IPropertyValues pvs) { - InjectionMetadata metadata; - if (injectionMetadataCache.TryGetValue(objectType, out metadata)) + // Fall back to class name as cache key, for backwards compatibility with custom callers. + var cacheKey = StringUtils.HasLength(objectName) ? objectName : objectType.Name; + injectionMetadataCache.TryGetValue(cacheKey, out var metadata); + + if (InjectionMetadata.NeedsRefresh(metadata, objectType)) { - return metadata; - } - - lock (injectionMetadataCache) - { - if (!injectionMetadataCache.TryGetValue(objectType, out metadata)) + lock (injectionMetadataCache) { - metadata = BuildAutowiringMetadata(objectType); - injectionMetadataCache.Add(objectType, metadata); + if (!injectionMetadataCache.TryGetValue(cacheKey, out metadata) + || InjectionMetadata.NeedsRefresh(metadata, objectType)) + { + metadata = BuildAutowiringMetadata(objectType); + injectionMetadataCache[cacheKey] = metadata; + } } } + return metadata; } @@ -304,71 +349,77 @@ namespace Spring.Objects.Factory.Attributes do { - foreach (var autowiredType in autowiredPropertyTypes) + for (var i = 0; i < autowiredPropertyTypes.Count; i++) { + var autowiredType = autowiredPropertyTypes[i]; var currElements = new List(); - foreach ( - var property in - objectType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | - BindingFlags.Instance)) + var properties = + objectType.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + + foreach (var property in properties) { var required = true; var attr = Attribute.GetCustomAttribute(property, autowiredType); - if (attr is AutowiredAttribute) + if (attr is AutowiredAttribute autowiredAttribute) { - required = ((AutowiredAttribute) attr).Required; + required = autowiredAttribute.Required; } + if (attr != null && property.DeclaringType == objectType) { - currElements.Add(new AutowiredPropertyElement(property, required)); + currElements.Add(new AutowiredPropertyElement(this, property, required)); } } - foreach ( - var field in - objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) + + var fields = objectType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + foreach (var field in fields) { var required = true; var attr = Attribute.GetCustomAttribute(field, autowiredType); - if (attr is AutowiredAttribute) + if (attr is AutowiredAttribute autowiredAttribute) { - required = ((AutowiredAttribute) attr).Required; + required = autowiredAttribute.Required; } + if (attr != null && field.DeclaringType == objectType) { - currElements.Add(new AutowiredFieldElement(field, required)); + currElements.Add(new AutowiredFieldElement(this, field, required)); } } - foreach ( - var method in - objectType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) + + var methods = objectType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + foreach (var method in methods) { var required = true; var attr = Attribute.GetCustomAttribute(method, autowiredType); - if (attr is AutowiredAttribute) + if (attr is AutowiredAttribute autowiredAttribute) { - required = ((AutowiredAttribute) attr).Required; + required = autowiredAttribute.Required; } + if (attr != null && method.DeclaringType == objectType) { if (method.IsStatic) { - logger.Warn( - m => m("Autowired annotation is not supported on static methods: " + method.Name)); + logger.Warn(m => m("Autowired annotation is not supported on static methods: " + method.Name)); continue; } + if (method.IsGenericMethod) { - logger.Warn( - m => m("Autowired annotation is not supported on generic methods: " + method.Name)); + logger.Warn(m => m("Autowired annotation is not supported on generic methods: " + method.Name)); continue; } - currElements.Add(new AutowiredMethodElement(method, required)); + + currElements.Add(new AutowiredMethodElement(this, method, required)); } } + elements.InsertRange(0, currElements); } + objectType = objectType.BaseType; - } while (objectType != null && objectType != typeof (Object)); + } while (objectType != null && objectType != typeof (object)); return new InjectionMetadata(objectType, elements); } @@ -376,7 +427,7 @@ namespace Spring.Objects.Factory.Attributes /// /// Register the specified bean as dependent on the autowired beans. /// - private static void RegisterDependentObjects(string objectName, IList autowiredObjectNames) + private void RegisterDependentObjects(string objectName, List autowiredObjectNames) { if (objectName == null) { @@ -392,34 +443,29 @@ namespace Spring.Objects.Factory.Attributes var dependsOn = new List(objectDefinition.DependsOn); foreach (var name in autowiredObjectNames) { - var autowiredObjectName = name as string; + var autowiredObjectName = name; if (!dependsOn.Contains(autowiredObjectName)) { dependsOn.Add(autowiredObjectName); - logger.Debug( - m => - m("Autowiring by type from object name '{0}' to object named '{1}'", objectName, - autowiredObjectName)); + logger.Debug(m => m("Autowiring by type from object name '{0}' to object named '{1}'", objectName, autowiredObjectName)); } } objectDefinition.DependsOn = dependsOn; } - private static object ResolvedCachedArgument(String objectName, Object cachedArgument) + private object ResolvedCachedArgument(string objectName, object cachedArgument) { - if (cachedArgument is DependencyDescriptor) + if (cachedArgument is DependencyDescriptor descriptor) { - var descriptor = (DependencyDescriptor) cachedArgument; return objectFactory.ResolveDependency(descriptor, objectName, null); } - else if (cachedArgument is RuntimeObjectReference) + + if (cachedArgument is RuntimeObjectReference runtimeObjectReference) { - return objectFactory.GetObject(((RuntimeObjectReference) cachedArgument).ObjectName); - } - else - { - return cachedArgument; + return objectFactory.GetObject(runtimeObjectReference.ObjectName); } + + return cachedArgument; } /// @@ -427,58 +473,58 @@ namespace Spring.Objects.Factory.Attributes /// private class AutowiredPropertyElement : InjectionMetadata.InjectedElement { - private readonly bool _required; + private readonly AutowiredAttributeObjectPostProcessor processor; + private readonly bool required; + private bool cached; + private object cachedFieldValue; - private bool _cached = false; - - private Object _cachedFieldValue; - - public AutowiredPropertyElement(PropertyInfo property, bool required) + public AutowiredPropertyElement(AutowiredAttributeObjectPostProcessor processor, PropertyInfo property, bool required) : base(property) { - _required = required; + this.processor = processor; + this.required = required; } - public override void Inject(Object instance, String objectName, IPropertyValues pvs) + public override void Inject(object instance, string objectName, IPropertyValues pvs) { var property = (PropertyInfo) Member; try { - Object value; - if (_cached) + object value; + if (cached) { - value = ResolvedCachedArgument(objectName, _cachedFieldValue); + value = processor.ResolvedCachedArgument(objectName, cachedFieldValue); } else { - var descriptor = new DependencyDescriptor(property, _required); + var descriptor = new DependencyDescriptor(property, required); var autowiredObjectNames = new List(); - value = objectFactory.ResolveDependency(descriptor, objectName, autowiredObjectNames); + value = processor.objectFactory.ResolveDependency(descriptor, objectName, autowiredObjectNames); lock (this) { - if (!_cached) + if (!cached) { - if (value != null || _required) + if (value != null || required) { - _cachedFieldValue = descriptor; - RegisterDependentObjects(objectName, autowiredObjectNames); + cachedFieldValue = descriptor; + processor.RegisterDependentObjects(objectName, autowiredObjectNames); if (autowiredObjectNames.Count == 1) { var autowiredBeanName = autowiredObjectNames[0]; - if (objectFactory.ContainsObject(autowiredBeanName)) + if (processor.objectFactory.ContainsObject(autowiredBeanName)) { - if (objectFactory.IsTypeMatch(autowiredBeanName, property.GetType())) + if (processor.objectFactory.IsTypeMatch(autowiredBeanName, property.GetType())) { - _cachedFieldValue = new RuntimeObjectReference(autowiredBeanName); + cachedFieldValue = new RuntimeObjectReference(autowiredBeanName); } } } } else { - _cachedFieldValue = null; + cachedFieldValue = null; } - _cached = true; + cached = true; } } } @@ -499,58 +545,58 @@ namespace Spring.Objects.Factory.Attributes /// private class AutowiredFieldElement : InjectionMetadata.InjectedElement { - private readonly bool _required; + private readonly AutowiredAttributeObjectPostProcessor processor; + private readonly bool required; + private bool cached; + private object cachedFieldValue; - private bool _cached = false; - - private Object _cachedFieldValue; - - public AutowiredFieldElement(FieldInfo field, bool required) + public AutowiredFieldElement(AutowiredAttributeObjectPostProcessor processor, FieldInfo field, bool required) : base(field) { - _required = required; + this.processor = processor; + this.required = required; } - public override void Inject(Object instance, String objectName, IPropertyValues pvs) + public override void Inject(object instance, string objectName, IPropertyValues pvs) { var field = (FieldInfo) Member; try { - Object value; - if (_cached) + object value; + if (cached) { - value = ResolvedCachedArgument(objectName, _cachedFieldValue); + value = processor.ResolvedCachedArgument(objectName, cachedFieldValue); } else { - var descriptor = new DependencyDescriptor(field, _required); + var descriptor = new DependencyDescriptor(field, required); var autowiredObjectNames = new List(); - value = objectFactory.ResolveDependency(descriptor, objectName, autowiredObjectNames); + value = processor.objectFactory.ResolveDependency(descriptor, objectName, autowiredObjectNames); lock (this) { - if (!_cached) + if (!cached) { - if (value != null || _required) + if (value != null || required) { - _cachedFieldValue = descriptor; - RegisterDependentObjects(objectName, autowiredObjectNames); + cachedFieldValue = descriptor; + processor.RegisterDependentObjects(objectName, autowiredObjectNames); if (autowiredObjectNames.Count == 1) { var autowiredBeanName = autowiredObjectNames[0] as string; - if (objectFactory.ContainsObject(autowiredBeanName)) + if (processor.objectFactory.ContainsObject(autowiredBeanName)) { - if (objectFactory.IsTypeMatch(autowiredBeanName, field.GetType())) + if (processor.objectFactory.IsTypeMatch(autowiredBeanName, field.GetType())) { - _cachedFieldValue = new RuntimeObjectReference(autowiredBeanName); + cachedFieldValue = new RuntimeObjectReference(autowiredBeanName); } } } } else { - _cachedFieldValue = null; + cachedFieldValue = null; } - _cached = true; + cached = true; } } } @@ -571,40 +617,40 @@ namespace Spring.Objects.Factory.Attributes /// private class AutowiredMethodElement : InjectionMetadata.InjectedElement { - private readonly bool _required; + private readonly AutowiredAttributeObjectPostProcessor processor; + private readonly bool required; + private bool cached; + private volatile object[] cachedMethodArguments; - private bool _cached = false; - - private volatile Object[] _cachedMethodArguments; - - public AutowiredMethodElement(MethodInfo method, bool required) + public AutowiredMethodElement(AutowiredAttributeObjectPostProcessor processor, MethodInfo method, bool required) : base(method) { - _required = required; + this.processor = processor; + this.required = required; } - public override void Inject(Object target, string objectName, IPropertyValues pvs) + public override void Inject(object target, string objectName, IPropertyValues pvs) { MethodInfo method = Member as MethodInfo; try { - Object[] arguments; - if (_cached) + object[] arguments; + if (cached) { arguments = ResolveCachedArguments(objectName); } else { Type[] paramTypes = method.GetParameters().Select(p => p.ParameterType).ToArray(); - arguments = new Object[paramTypes.Length]; + arguments = new object[paramTypes.Length]; var descriptors = new DependencyDescriptor[paramTypes.Length]; var autowiredBeanNames = new List(); for (int i = 0; i < arguments.Length; i++) { MethodParameter methodParam = new MethodParameter(method, i); - descriptors[i] = new DependencyDescriptor(methodParam, _required); - arguments[i] = objectFactory.ResolveDependency(descriptors[i], objectName, autowiredBeanNames); - if (arguments[i] == null && !_required) + descriptors[i] = new DependencyDescriptor(methodParam, required); + arguments[i] = processor.objectFactory.ResolveDependency(descriptors[i], objectName, autowiredBeanNames); + if (arguments[i] == null && !required) { arguments = null; break; @@ -612,26 +658,26 @@ namespace Spring.Objects.Factory.Attributes } lock (this) { - if (!_cached) + if (!cached) { if (arguments != null) { - _cachedMethodArguments = new Object[arguments.Length]; + cachedMethodArguments = new object[arguments.Length]; for (int i = 0; i < arguments.Length; i++) { - _cachedMethodArguments[i] = descriptors[i]; + cachedMethodArguments[i] = descriptors[i]; } - RegisterDependentObjects(objectName, autowiredBeanNames); + processor.RegisterDependentObjects(objectName, autowiredBeanNames); if (autowiredBeanNames.Count == paramTypes.Length) { for (int i = 0; i < paramTypes.Length; i++) { string autowiredBeanName = autowiredBeanNames[i] as string; - if (objectFactory.ContainsObject(autowiredBeanName)) + if (processor.objectFactory.ContainsObject(autowiredBeanName)) { - if (objectFactory.IsTypeMatch(autowiredBeanName, paramTypes[i])) + if (processor.objectFactory.IsTypeMatch(autowiredBeanName, paramTypes[i])) { - _cachedMethodArguments[i] = + cachedMethodArguments[i] = new RuntimeObjectReference(autowiredBeanName); } } @@ -640,9 +686,9 @@ namespace Spring.Objects.Factory.Attributes } else { - _cachedMethodArguments = null; + cachedMethodArguments = null; } - _cached = true; + cached = true; } } } @@ -657,16 +703,16 @@ namespace Spring.Objects.Factory.Attributes } } - private Object[] ResolveCachedArguments(string objectName) + private object[] ResolveCachedArguments(string objectName) { - if (_cachedMethodArguments == null) + if (cachedMethodArguments == null) { return null; } - Object[] arguments = new Object[_cachedMethodArguments.Length]; + object[] arguments = new object[cachedMethodArguments.Length]; for (int i = 0; i < arguments.Length; i++) { - arguments[i] = ResolvedCachedArgument(objectName, _cachedMethodArguments[i]); + arguments[i] = processor.ResolvedCachedArgument(objectName, cachedMethodArguments[i]); } return arguments; } diff --git a/src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs b/src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs index 92157881..c91f3654 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Attributes/InjectionMetadata.cs @@ -22,96 +22,93 @@ using System; using System.Collections.Generic; using System.Reflection; using Common.Logging; - using Spring.Objects.Factory.Support; namespace Spring.Objects.Factory.Attributes { - /// - /// Internal class for managing injection metadata. - /// Not intended for direct use in applications. - /// - public class InjectionMetadata - { - private static readonly ILog Logger = LogManager.GetLogger(); + /// + /// Internal class for managing injection metadata. + /// Not intended for direct use in applications. + /// + public class InjectionMetadata + { + private static readonly ILog Logger = LogManager.GetLogger(); - private readonly IList _injectedElements; + private readonly Type targetType; + private readonly IList _injectedElements; + /// + /// + /// + /// + public InjectionMetadata(Type targetType, IList elements) + { + this.targetType = targetType; + _injectedElements = new List(); + if (elements.Count > 0) + { + foreach (var element in elements) + { + Logger.Debug(m => m("Found injected element on class [" + targetType.Name + "]: " + element)); + _injectedElements.Add(element); + } + } + } - /// - /// - /// - /// - public InjectionMetadata(Type targetType, IList elements) - { - _injectedElements = new List(); - if (elements.Count > 0) - { - foreach (var element in elements) - { - Logger.Debug(m => m("Found injected element on class [" + targetType.Name + "]: " + element)); - _injectedElements.Add(element); - } - } - } + /// + /// + /// + public void CheckConfigMembers(RootObjectDefinition objectDefinition) + { + } - /// - /// - /// - public void CheckConfigMembers(RootObjectDefinition objectDefinition) - { - } + /// + /// Inject values for members into object instance + /// + /// + /// + /// + public void Inject(object instance, string objectName, IPropertyValues pvs) + { + for (var i = 0; i < _injectedElements.Count; i++) + { + var element = _injectedElements[i]; + Logger.Debug(m => m("Processing injected method of bean '{0}': {1}", objectName, element)); + element.Inject(instance, objectName, pvs); + } + } + /// + /// Represents an element that needs to be injected + /// + public abstract class InjectedElement + { + /// + /// Instantiates a new inject element + /// + /// + protected InjectedElement(MemberInfo member) + { + Member = member; + } - /// - /// Inject values for members into object instance - /// - /// - /// - /// - public void Inject(Object instance, string objectName, IPropertyValues pvs) - { - if (_injectedElements.Count == 0) - return; + /// + /// The Property, field, method or constructor info. + /// + public MemberInfo Member { get; } - foreach(var element in _injectedElements) - { - Logger.Debug(m => m("Processing injected method of bean '{0}': {1}", objectName, element)); - element.Inject(instance, objectName, pvs); - } - } + /// + /// Ececuted to inject value to associated memeber info + /// + /// + /// + /// + public abstract void Inject(object target, string requestingObjectName, IPropertyValues pvs); + } - /// - /// Represents an element that needs to be injected - /// - public abstract class InjectedElement - { - /// - /// The Property, field, method or constructor info - /// - private readonly MemberInfo _member; - - /// - /// Instantiates a new inject element - /// - /// - protected InjectedElement(MemberInfo member) - { - _member = member; - } - - public MemberInfo Member - { - get { return _member; } - } - - /// - /// Ececuted to inject value to associated memeber info - /// - /// - /// - /// - public abstract void Inject(object target, string requestingObjectName, IPropertyValues pvs); - } - } + public static bool NeedsRefresh(InjectionMetadata metadata, Type type) + { + return (metadata == null || metadata.targetType != type); + } + } } diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableListableObjectFactory.cs index 615e64f7..bb4b982c 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableListableObjectFactory.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,6 @@ * limitations under the License. */ -#endregion - -#region Imports - - - #endregion using System; @@ -154,12 +148,12 @@ namespace Spring.Objects.Factory.Config /// ApplicationContext instance that the object is living in. /// /// Note there are no such default types registered in a plain IObjectFactory, - /// not even for the BeanFactory interface itself. + /// not even for the IObjectFactory interface itself. /// /// /// Type of the dependency to register. /// This will typically be a base interface such as IObjectFactory, with extensions of it resolved - /// as well if declared as an autowiring dependency (e.g. IListableBeanFactory), + /// as well if declared as an autowiring dependency (e.g. IListableObjectFactory), /// as long as the given value actually implements the extended interface. /// /// The autowired value. This may also be an @@ -169,7 +163,7 @@ namespace Spring.Objects.Factory.Config /// /// Determines whether the specified object qualifies as an autowire candidate, - /// to be injected into other beans which declare a dependency of matching type. + /// to be injected into other objects which declare a dependency of matching type. /// This method checks ancestor factories as well. /// /// Name of the object to check. @@ -179,5 +173,33 @@ namespace Spring.Objects.Factory.Config /// /// if there is no object with the given name. bool IsAutowireCandidate(string objectName, DependencyDescriptor descriptor); + + + /// + /// Clear the merged object definition cache, removing entries for objects + /// which are not considered eligible for full metadata caching yet. + /// + /// + /// Typically triggered after changes to the original object definitions, + /// e.g. after applying a . Note that metadata + /// for objects which have already been created at this point will be kept around. + /// + /// + void ClearMetadataCache(); + + /// + /// Freeze all object definitions, signalling that the registered object definitions + /// will not be modified or post-processed any further. + /// + /// + /// This allows the factory to aggressively cache object definition metadata. + /// + void FreezeConfiguration(); + + /// + /// Return whether this factory's object definitions are frozen, + /// i.e. are not supposed to be modified or post-processed any further. + /// + bool ConfigurationFrozen { get; } } } diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs index e81168a5..dd357903 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/IConfigurableObjectFactory.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +18,10 @@ #endregion -#region Imports - using System; using System.ComponentModel; using Spring.Util; -#endregion - namespace Spring.Objects.Factory.Config { /// diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/IInstantiationAwareObjectPostProcessor.cs b/src/Spring/Spring.Core/Objects/Factory/Config/IInstantiationAwareObjectPostProcessor.cs index f7a44bab..4fee589b 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/IInstantiationAwareObjectPostProcessor.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/IInstantiationAwareObjectPostProcessor.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs b/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs index ff010302..059998d2 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/ObjectDefinitionHolder.cs @@ -1,7 +1,5 @@ -#region License - /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,18 +14,12 @@ * limitations under the License. */ -#endregion - -#region Imports - using System; using System.Collections.Generic; using Spring.Objects.Factory.Xml; using Spring.Util; -#endregion - namespace Spring.Objects.Factory.Config { /// @@ -55,11 +47,9 @@ namespace Spring.Objects.Factory.Config [Serializable] public class ObjectDefinitionHolder { - private IObjectDefinition objectDefinition; - private string objectName; - private IList aliases; - - #region Constructor () / Destructor + private readonly IObjectDefinition objectDefinition; + private readonly string objectName; + private readonly List aliases; /// /// Creates a new instance of the @@ -88,33 +78,27 @@ namespace Spring.Objects.Factory.Config /// Any aliases for the supplied /// public ObjectDefinitionHolder( - IObjectDefinition definition, string name, IList aliases) + IObjectDefinition definition, + string name, + IReadOnlyList aliases) { - this.objectDefinition = definition; - this.objectName = name; - this.aliases = aliases ?? new List(0); + objectDefinition = definition; + objectName = name; + this.aliases = aliases != null && aliases.Count > 0 + ? new List(aliases) + : null; } - #endregion - - #region Properties - /// /// The held by this /// instance. /// - public IObjectDefinition ObjectDefinition - { - get { return objectDefinition; } - } + public IObjectDefinition ObjectDefinition => objectDefinition; /// /// The name of the object definition. /// - public string ObjectName - { - get { return objectName; } - } + public string ObjectName => objectName; /// /// Any aliases for the object definition. @@ -127,10 +111,7 @@ namespace Spring.Objects.Factory.Config /// array will be returned. ///

/// - public IList Aliases - { - get { return aliases; } - } + public IReadOnlyList Aliases => aliases ?? StringUtils.EmptyStringsList; /// /// Checks wether a givin candidate name has a defined object or alias @@ -139,10 +120,8 @@ namespace Spring.Objects.Factory.Config /// public bool MatchesName(string candidateName) { - return (!string.IsNullOrEmpty(candidateName) && - (candidateName.Equals(ObjectName) || Aliases.Contains(candidateName))); + return !string.IsNullOrEmpty(candidateName) + && (candidateName == ObjectName || aliases?.Contains(candidateName) == true); } - - #endregion } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs index 2b0b3b30..ee389399 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/PropertyPlaceholderConfigurer.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -240,7 +240,7 @@ namespace Spring.Objects.Factory.Config PlaceholderResolveHandlerAdapter resolveAdapter = new PlaceholderResolveHandlerAdapter(this, props); ObjectDefinitionVisitor visitor = new ObjectDefinitionVisitor(resolveAdapter.ParseAndResolveVariables); - IList objectDefinitionNames = factory.GetObjectDefinitionNames(includeAncestors); + var objectDefinitionNames = factory.GetObjectDefinitionNames(includeAncestors); for (int i = 0; i < objectDefinitionNames.Count; ++i) { string name = objectDefinitionNames[i]; diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs b/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs index bdade2da..fc3304c2 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/VariablePlaceholderConfigurer.cs @@ -1,5 +1,3 @@ -#region License - /* * Copyright 2002-2010 the original author or authors. * @@ -16,8 +14,6 @@ * limitations under the License. */ -#endregion - using System; using System.Collections; using System.Collections.Generic; @@ -75,8 +71,6 @@ namespace Spring.Objects.Factory.Config /// public static readonly string DefaultPlaceholderSuffix = "}"; - #region Fields - private int order = Int32.MaxValue; // default: same as non-Ordered private bool includeAncestors; @@ -86,8 +80,6 @@ namespace Spring.Objects.Factory.Config private IList variableSourceList = new ArrayList(); - #endregion - /// /// Create a new instance without any variable sources /// @@ -111,8 +103,6 @@ namespace Spring.Objects.Factory.Config this.VariableSources = variableSources; } - #region Properties - /// /// Sets the list of s that will be used to resolve placeholder names. /// @@ -166,10 +156,6 @@ namespace Spring.Objects.Factory.Config set { includeAncestors = value; } } - #endregion - - #region IObjectFactoryPostProcessor Members - /// /// Modify the application context's internal object factory after its /// standard initialization. @@ -216,10 +202,6 @@ namespace Spring.Objects.Factory.Config } } - #endregion - - #region IOrdered Members - /// /// Return the order value of this object, where a higher value means greater in /// terms of sorting. @@ -232,8 +214,6 @@ namespace Spring.Objects.Factory.Config set { order = value; } } - #endregion - /// /// Apply the property replacement using the specified s for all /// object in the supplied @@ -252,7 +232,7 @@ namespace Spring.Objects.Factory.Config TextProcessor tp = new TextProcessor(this, compositeVariableSource); ObjectDefinitionVisitor visitor = new ObjectDefinitionVisitor(new ObjectDefinitionVisitor.ResolveHandler(tp.ParseAndResolveVariables)); - IList objectDefinitionNames = factory.GetObjectDefinitionNames(includeAncestors); + var objectDefinitionNames = factory.GetObjectDefinitionNames(includeAncestors); for (int i = 0; i < objectDefinitionNames.Count; ++i) { string name = objectDefinitionNames[i]; @@ -273,8 +253,6 @@ namespace Spring.Objects.Factory.Config } } - #region Helper class - private class TextProcessor { private readonly ILog logger = LogManager.GetLogger(typeof(TextProcessor)); @@ -323,8 +301,6 @@ namespace Spring.Objects.Factory.Config string resolvedValue = variableSource.ResolveVariable(placeholder); resolvedValue = ParseAndResolveVariables(resolvedValue, visitedPlaceholders); - #region Instrumentation - if (logger.IsDebugEnabled) { logger.Debug(string.Format( @@ -332,8 +308,6 @@ namespace Spring.Objects.Factory.Config "Resolving placeholder '{0}' to '{1}'.", placeholder, resolvedValue)); } - #endregion - if (resolvedValue == null && startIndex == 0 && strVal.Length <= endIndex + owner.placeholderSuffix.Length) @@ -395,7 +369,5 @@ namespace Spring.Objects.Factory.Config return false; } } - - #endregion } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs index 305629eb..76d3a203 100644 --- a/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/IListableObjectFactory.cs @@ -93,7 +93,7 @@ namespace Spring.Objects.Factory /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - IList GetObjectDefinitionNames(); + IReadOnlyList GetObjectDefinitionNames(); /// /// Return the names of all objects defined in this factory, if includeAncestors is true @@ -104,7 +104,7 @@ namespace Spring.Objects.Factory /// The names of all objects defined in this factory, if includeAncestors is true includes all /// objects defined in parent factories, or an empty array if none are defined. /// - IList GetObjectDefinitionNames(bool includeAncestors); + IReadOnlyList GetObjectDefinitionNames(bool includeAncestors); /// /// Return the names of objects matching the given @@ -129,7 +129,7 @@ namespace Spring.Objects.Factory /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - IList GetObjectNamesForType(Type type); + IReadOnlyList GetObjectNamesForType(Type type); /// /// Return the names of objects matching the given @@ -154,8 +154,7 @@ namespace Spring.Objects.Factory /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - IList GetObjectNames(); - + IReadOnlyList GetObjectNames(); /// /// Return the names of objects matching the given @@ -192,44 +191,44 @@ namespace Spring.Objects.Factory /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - IList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects); + IReadOnlyList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects); - /// - /// Return the names of objects matching the given - /// (including subclasses), judging from the object definitions. - /// - /// - ///

- /// Does consider objects created by s, - /// or rather it considers the type of objects created by - /// (which means that - /// s will be instantiated). - ///

- ///

- /// Does not consider any hierarchy this factory may participate in. - /// Use - /// to include beans in ancestor factories too. - /// <p>Note: Does <i>not</i> ignore singleton objects that have been registered - /// by other means than bean definitions. - ///

- ///
- /// - /// The (class or interface) to match, or - /// for all object names. - /// - /// - /// Whether to include prototype objects too or just singletons (also applies to - /// s). - /// - /// - /// Whether to include s too - /// or just normal objects. - /// - /// - /// The names of all objects defined in this factory, or an empty array if none - /// are defined. - /// - IList GetObjectNames(bool includePrototypes, bool includeFactoryObjects); + /// + /// Return the names of objects matching the given + /// (including subclasses), judging from the object definitions. + /// + /// + ///

+ /// Does consider objects created by s, + /// or rather it considers the type of objects created by + /// (which means that + /// s will be instantiated). + ///

+ ///

+ /// Does not consider any hierarchy this factory may participate in. + /// Use + /// to include beans in ancestor factories too. + /// <p>Note: Does <i>not</i> ignore singleton objects that have been registered + /// by other means than bean definitions. + ///

+ ///
+ /// + /// The (class or interface) to match, or + /// for all object names. + /// + /// + /// Whether to include prototype objects too or just singletons (also applies to + /// s). + /// + /// + /// Whether to include s too + /// or just normal objects. + /// + /// + /// The names of all objects defined in this factory, or an empty array if none + /// are defined. + /// + IReadOnlyList GetObjectNames(bool includePrototypes, bool includeFactoryObjects); /// /// Return the object instances that match the given object @@ -258,7 +257,7 @@ namespace Spring.Objects.Factory /// /// If the objects could not be created. /// - IDictionary GetObjectsOfType(Type type); + IReadOnlyDictionary GetObjectsOfType(Type type); /// /// Return the object instances that match the given object @@ -287,7 +286,7 @@ namespace Spring.Objects.Factory /// /// If the objects could not be created. /// - IDictionary GetObjects(); + IReadOnlyDictionary GetObjects(); /// /// Return the object instances that match the given object @@ -315,7 +314,7 @@ namespace Spring.Objects.Factory /// /// If the objects could not be created. /// - IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects); + IReadOnlyDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects); /// /// Return the object instances that match the given object @@ -343,6 +342,6 @@ namespace Spring.Objects.Factory /// /// If the objects could not be created. /// - IDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects); + IReadOnlyDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects); } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs index c7fdf4b6..4eac7afc 100644 --- a/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/IObjectFactory.cs @@ -210,21 +210,21 @@ namespace Spring.Objects.Factory /// True if an object with the given name is defined. bool ContainsObject(string name); - /// - /// Return the aliases for the given object name, if defined. - /// - /// - /// - /// Will ask the parent factory if the object cannot be found in this factory - /// instance. - /// - /// - /// The object name to check for aliases. - /// The aliases, or an empty array if none. - /// - /// If there's no such object definition. - /// - IList GetAliases(string name); + /// + /// Return the aliases for the given object name, if defined. + /// + /// + /// + /// Will ask the parent factory if the object cannot be found in this factory + /// instance. + /// + /// + /// The object name to check for aliases. + /// The aliases, or an empty array if none. + /// + /// If there's no such object definition. + /// + IReadOnlyList GetAliases(string name); #if !MONO /// diff --git a/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs b/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs index 55299166..0334a12a 100644 --- a/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs +++ b/src/Spring/Spring.Core/Objects/Factory/ObjectFactoryUtils.cs @@ -115,7 +115,7 @@ namespace Spring.Objects.Factory /// /// The object factory. /// The array of object names, or an empty array if none. - public static IList ObjectNamesIncludingAncestors(IListableObjectFactory factory) + public static IReadOnlyList ObjectNamesIncludingAncestors(IListableObjectFactory factory) { return ObjectNamesForTypeIncludingAncestors(factory, typeof(object)); } @@ -155,7 +155,7 @@ namespace Spring.Objects.Factory /// /// The array of object names, or an empty array if none. /// - public static IList ObjectNamesForTypeIncludingAncestors( + public static List ObjectNamesForTypeIncludingAncestors( IListableObjectFactory factory, Type type, bool includePrototypes, bool includeFactoryObjects) { @@ -202,7 +202,7 @@ namespace Spring.Objects.Factory /// /// The array of object names, or an empty array if none. /// - public static IList ObjectNamesForTypeIncludingAncestors(IListableObjectFactory factory, Type type) + public static IReadOnlyList ObjectNamesForTypeIncludingAncestors(IListableObjectFactory factory, Type type) { return factory.GetObjectNamesForType(type); } @@ -235,21 +235,21 @@ namespace Spring.Objects.Factory /// The of object instances, or an /// empty if none. /// - public static IDictionary ObjectsOfTypeIncludingAncestors( + public static Dictionary ObjectsOfTypeIncludingAncestors( IListableObjectFactory factory, Type type, bool includePrototypes, bool includeFactoryObjects) { Dictionary result = new Dictionary(); - foreach (KeyValuePair entry in - factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects)) + foreach (var entry in factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects)) { result.Add(entry.Key, entry.Value); } + IListableObjectFactory pof = GetParentListableObjectFactoryIfAny(factory); if (pof != null) { IHierarchicalObjectFactory hof = (IHierarchicalObjectFactory)factory; - IDictionary parentResult = ObjectsOfTypeIncludingAncestors(pof, type, includePrototypes, includeFactoryObjects); + Dictionary parentResult = ObjectsOfTypeIncludingAncestors(pof, type, includePrototypes, includeFactoryObjects); foreach (string objectName in parentResult.Keys) { if (!result.ContainsKey(objectName) && !hof.ContainsLocalObject(objectName)) @@ -295,7 +295,7 @@ namespace Spring.Objects.Factory IListableObjectFactory factory, Type type, bool includePrototypes, bool includeFactoryObjects) { - IDictionary objectsOfType = ObjectsOfTypeIncludingAncestors(factory, type, includePrototypes, includeFactoryObjects); + var objectsOfType = ObjectsOfTypeIncludingAncestors(factory, type, includePrototypes, includeFactoryObjects); return GrabTheOnlyObject(objectsOfType, type); } @@ -331,7 +331,7 @@ namespace Spring.Objects.Factory public static object ObjectOfType(IListableObjectFactory factory, Type type, bool includePrototypes, bool includeFactoryObjects) { - IDictionary objectsOfType = factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects); + var objectsOfType = factory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects); return GrabTheOnlyObject(objectsOfType, type); } @@ -433,7 +433,7 @@ namespace Spring.Objects.Factory return null; } - private static object GrabTheOnlyObject(IDictionary objectsOfType, Type type) + private static object GrabTheOnlyObject(IReadOnlyDictionary objectsOfType, Type type) { if (objectsOfType.Count == 1) { diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs index 82f03b74..c6b809ea 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractAutowireCapableObjectFactory.cs @@ -56,6 +56,24 @@ namespace Spring.Objects.Factory.Support [Serializable] public abstract class AbstractAutowireCapableObjectFactory : AbstractObjectFactory, IAutowireCapableObjectFactory { + + private IInstantiationStrategy instantiationStrategy = new MethodInjectingInstantiationStrategy(); + + /// + /// Cache of filtered PropertyInfos: object Type -> PropertyInfo array + /// + private readonly ConcurrentDictionary> filteredPropertyDescriptorsCache = new ConcurrentDictionary>(); + + /// + /// Dependency interfaces to ignore on dependency check and autowire, as Set of + /// Class objects. By default, only the IObjectFactoryAware and IObjectNameAware + /// interfaces are ignored. + /// + private readonly HybridSet ignoredDependencyInterfaces = new HybridSet(); + + [NonSerialized] + private ObjectDefinitionValueResolver cachedValueResolver; + /// /// The used during the invocation and /// searching for of methods. @@ -226,7 +244,7 @@ namespace Spring.Objects.Factory.Support RootObjectDefinition definition = GetMergedObjectDefinition(name, true); if (definition != null) { - log.Debug(string.Format("configuring object '{0}' using definition '{1}'", instance, name)); + log.Debug($"configuring object '{instance}' using definition '{name}'"); ApplyPropertyValues(name, definition, new ObjectWrapper(instance), definition.PropertyValues); } } @@ -248,6 +266,7 @@ namespace Spring.Objects.Factory.Support /// public override void ApplyObjectPropertyValues(object instance, string name, IObjectDefinition definition) { + MarkObjectAsCreated(name); ApplyPropertyValues(name, new RootObjectDefinition(definition), new ObjectWrapper(instance), definition.PropertyValues); } @@ -389,7 +408,7 @@ namespace Spring.Objects.Factory.Support /// protected virtual ObjectDefinitionValueResolver CreateValueResolver() { - return new ObjectDefinitionValueResolver(this); + return cachedValueResolver ?? (cachedValueResolver =new ObjectDefinitionValueResolver(this)); } /// @@ -481,7 +500,7 @@ namespace Spring.Objects.Factory.Support // to support styles of field injection. bool continueWithPropertyPopulation = true; - if (HasInstantiationAwareBeanPostProcessors) + if (HasInstantiationAwareObjectPostProcessors) { for (var i = 0; i < ObjectPostProcessors.Count; i++) { @@ -533,7 +552,7 @@ namespace Spring.Objects.Factory.Support //DependencyCheck(name, definition, wrapper, properties); - bool hasInstAwareOpps = HasInstantiationAwareBeanPostProcessors; + bool hasInstAwareOpps = HasInstantiationAwareObjectPostProcessors; bool needsDepCheck = (definition.DependencyCheck != DependencyCheckingMode.None); if (hasInstAwareOpps || needsDepCheck) @@ -1020,7 +1039,7 @@ namespace Spring.Objects.Factory.Support /// protected virtual ConstructorInfo[] DetermineConstructorsFromObjectPostProcessors(Type objectType, string objectName) { - if (HasInstantiationAwareBeanPostProcessors) + if (HasInstantiationAwareObjectPostProcessors) { for (var i = 0; i < ObjectPostProcessors.Count; i++) { @@ -1142,7 +1161,7 @@ namespace Spring.Objects.Factory.Support } IList filteredPropInfo = FilterPropertyInfoForDependencyCheck(wrapper); - if (HasInstantiationAwareBeanPostProcessors) + if (HasInstantiationAwareObjectPostProcessors) { for (var i = 0; i < ObjectPostProcessors.Count; i++) { @@ -1699,6 +1718,7 @@ namespace Spring.Objects.Factory.Support /// public override object ConfigureObject(object target, string name) { + MarkObjectAsCreated(name); RootObjectDefinition definition = GetMergedObjectDefinition(name, true); if (definition != null) { @@ -1964,20 +1984,6 @@ namespace Spring.Objects.Factory.Support DependencyDescriptor descriptor, string objectName, IList autowiredObjectNames); - - private IInstantiationStrategy instantiationStrategy = new MethodInjectingInstantiationStrategy(); - - /// - /// Cache of filtered PropertyInfos: object Type -> PropertyInfo array - /// - private readonly ConcurrentDictionary> filteredPropertyDescriptorsCache = new ConcurrentDictionary>(); - - /// - /// Dependency interfaces to ignore on dependency check and autowire, as Set of - /// Class objects. By default, only the IObjectFactoryAware and IObjectNameAware - /// interfaces are ignored. - /// - private readonly HybridSet ignoredDependencyInterfaces = new HybridSet(); } internal class UnsatisfiedDependencyExceptionData diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs index a5750fca..6c1f4bb8 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs @@ -24,7 +24,6 @@ using System.ComponentModel; using Common.Logging; using Spring.Collections; -using Spring.Collections.Generic; using Spring.Core; using Spring.Core.TypeConversion; using Spring.Objects.Factory.Config; @@ -53,59 +52,6 @@ namespace Spring.Objects.Factory.Support [Serializable] public abstract class AbstractObjectFactory : IConfigurableObjectFactory { - [Serializable] - private class LogicalThreadContextSetVariable : IDisposable - { - private readonly string name = Guid.NewGuid().ToString(); - - public HashSet Value - { - get - { - if (!(LogicalThreadContext.GetData(name) is HashSet set)) - { - set = new HashSet(); - LogicalThreadContext.SetData(name, set); - } - return set; - } - } - - public void Dispose() - { - LogicalThreadContext.FreeNamedDataSlot(name); - } - } - - /// - /// Makes a distinction between sort order and object identity. - /// This is important when used with , since most - /// implementations assume Order == Identity - /// - [Serializable] - private class ObjectOrderComparator : OrderComparator - { - /// - /// Handle the case when both objects have equal sort order priority. By default returns 0, - /// but may be overriden for handling special cases. - /// - /// The first object to compare. - /// The second object to compare. - /// - /// -1 if first object is less then second, 1 if it is greater, or 0 if they are equal. - /// - protected override int CompareEqualOrder(object o1, object o2) - { - if (ReferenceEquals(o1, o2)) - return 0; - if (o1 == null) - return 1; - if (o2 == null) - return -1; - return o1.GetHashCode().CompareTo(o2.GetHashCode()); - } - } - /// /// Marker object to be temporarily registered in the singleton cache, /// while instantiating an object (in order to be able to detect circular references). @@ -147,7 +93,7 @@ namespace Spring.Objects.Factory.Support /// /// Names of object that have already been created at least once /// - private Collections.Generic.ISet alreadyCreated = new SynchronizedSet(new HashedSet()); + private readonly HashSet alreadyCreated = new HashSet(); /// /// Creates a new instance of the @@ -165,7 +111,8 @@ namespace Spring.Objects.Factory.Support /// protected AbstractObjectFactory() : this(true) - { } + { + } /// /// Creates a new instance of the @@ -247,12 +194,18 @@ namespace Spring.Objects.Factory.Support /// /// Returns, whether this object factory instance contains objects. /// - protected bool HasInstantiationAwareBeanPostProcessors => hasInstantiationAwareBeanPostProcessors; + protected bool HasInstantiationAwareObjectPostProcessors => hasInstantiationAwareObjectPostProcessors; /// /// Returns, whether this object factory instance contains objects. /// - protected bool HasDestructionAwareBeanPostProcessors => hasDestructionAwareBeanPostProcessors; + protected bool HasDestructionAwareObjectPostProcessors => hasDestructionAwareObjectPostProcessors; + + /// + /// Check whether this factory's bean creation phase already started, + /// i.e. whether any bean has been marked as created in the meantime. + /// + protected bool HasObjectCreationStarted => alreadyCreated.Count > 0; /// /// Return an instance (possibly shared or independent) of the given object name. @@ -690,14 +643,7 @@ namespace Spring.Objects.Factory.Support /// protected RootObjectDefinition GetMergedLocalObjectDefinition(string objectName) { - // Quick check on the concurrent map first, with minimal locking. - RootObjectDefinition mbd = null; - - if (mergedObjectDefinitions.ContainsKey(objectName)) - { - mbd = mergedObjectDefinitions[objectName] as RootObjectDefinition; - } - + mergedObjectDefinitions.TryGetValue(objectName, out var mbd); return mbd; // ?? GetMergedObjectDefinition(objectName, GetObjectDefinition(objectName)); } @@ -708,7 +654,7 @@ namespace Spring.Objects.Factory.Support /// /// true if [is object eligible for metadata caching] [the specified bean name]; otherwise, false. /// - protected bool IsObjectEligibleForMetadataCaching(string beanName) + protected virtual bool IsObjectEligibleForMetadataCaching(string beanName) { return alreadyCreated.Contains(beanName); } @@ -835,6 +781,45 @@ namespace Spring.Objects.Factory.Support return null; } } + + /// + /// Mark the specified bean as already created (or about to be created). + /// + /// + /// This allows the bean factory to optimize its caching for repeated + /// creation of the specified bean. + /// + /// The name of the object. + protected void MarkObjectAsCreated(string objectName) + { + if (alreadyCreated.Contains(objectName)) + { + return; + } + + lock (mergedObjectDefinitions) + { + if (!alreadyCreated.Contains(objectName)) + { + // Let the bean definition get re-merged now that we're actually creating + // the object... just in case some of its metadata changed in the meantime. + ClearMergedObjectDefinition(objectName); + alreadyCreated.Add(objectName); + } + } + } + + /// + /// Perform appropriate cleanup of cached metadata after bean creation failed. + /// + /// The name of the object + protected void CleanupAfterObjectCreationFailure(string objectName) + { + lock (mergedObjectDefinitions) + { + alreadyCreated.Remove(objectName); + } + } /// /// Predict the eventual object type (of the processed object instance) for the @@ -1581,6 +1566,37 @@ namespace Spring.Objects.Factory.Support */ } } + + /// + /// Remove the merged bean definition for the specified bean, + /// recreating it on next access. + /// + /// The bean name to clear the merged definition for + protected void ClearMergedObjectDefinition(string objectName) + { + mergedObjectDefinitions.TryRemove(objectName, out _); + } + + /// + /// Clear the merged object definition cache, removing entries for objects + /// which are not considered eligible for full metadata caching yet. + /// + /// + /// Typically triggered after changes to the original object definitions, + /// e.g. after applying a . Note that metadata + /// for objects which have already been created at this point will be kept around. + /// + public virtual void ClearMetadataCache() + { + var keys = new List(mergedObjectDefinitions.Keys); + foreach (var key in keys) + { + if (!IsObjectEligibleForMetadataCaching(key)) + { + mergedObjectDefinitions.TryRemove(key, out _); + } + } + } /// /// Gets the temporary object that is placed @@ -1607,17 +1623,17 @@ namespace Spring.Objects.Factory.Support /// /// String Resolver applied to Autowired value injections /// - private SortedSet embeddedValueResolvers = new SortedSet(new ObjectOrderComparator()); + private SortedSet embeddedValueResolvers = new SortedSet(ObjectOrderComparator.ObjectOrderComparatorInstance); /// /// Indicates whether any IInstantiationAwareBeanPostProcessors have been registered /// - private bool hasInstantiationAwareBeanPostProcessors; + private bool hasInstantiationAwareObjectPostProcessors; /// /// Indicates whether any IDestructionAwareBeanPostProcessors have been registered /// - private bool hasDestructionAwareBeanPostProcessors; + private bool hasDestructionAwareObjectPostProcessors; private bool caseSensitive; private OrderedDictionary aliasMap; @@ -1807,7 +1823,12 @@ namespace Spring.Objects.Factory.Support /// Return the aliases for the given object name, if defined. /// /// . - public IList GetAliases(string name) + public IReadOnlyList GetAliases(string name) + { + return DoGetAliases(name); + } + + internal List DoGetAliases(string name) { string objectName = TransformedObjectName(name); // check if object actually exists in this object factory... @@ -1830,8 +1851,9 @@ namespace Spring.Objects.Factory.Support // not found, so check parent... if (ParentObjectFactory != null) { - return ParentObjectFactory.GetAliases(objectName); + return new List(ParentObjectFactory.GetAliases(objectName)); } + throw new NoSuchObjectDefinitionException(objectName, ToString()); } @@ -2077,7 +2099,7 @@ namespace Spring.Objects.Factory.Support protected object GetObjectInternal(string name, Type requiredType, object[] arguments, bool suppressConfigure) { object monitor = new object(); - const int INDENT = 3; + const int indent = 3; bool hasErrors = false; try { @@ -2086,7 +2108,7 @@ namespace Spring.Objects.Factory.Support if (log.IsDebugEnabled) { - log.Debug(string.Format("{2}GetObjectInternal: obtaining instance for name {0} => canonical name {1}", name, objectName, new string(' ', nestingCount * INDENT))); + log.Debug(string.Format("{2}GetObjectInternal: obtaining instance for name {0} => canonical name {1}", name, objectName, new string(' ', nestingCount * indent))); } object instance = null; @@ -2121,9 +2143,13 @@ namespace Spring.Objects.Factory.Support throw new ObjectCurrentlyInCreationException(name); } + if (!suppressConfigure) + { + MarkObjectAsCreated(objectName); + } + // check if object definition exists - RootObjectDefinition mergedObjectDefinition = null; - mergedObjectDefinition = GetMergedObjectDefinition(objectName, false); + var mergedObjectDefinition = GetMergedObjectDefinition(objectName, false); if (mergedObjectDefinition == null) { if (ParentObjectFactory != null) @@ -2133,8 +2159,7 @@ namespace Spring.Objects.Factory.Support throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]"); } - if (arguments != null - || suppressConfigure) + if (arguments != null || suppressConfigure) { // Clone ObjectDefinition mergedObjectDefinition = CreateRootObjectDefinition(mergedObjectDefinition); @@ -2186,7 +2211,6 @@ namespace Spring.Objects.Factory.Support } catch { - lock (monitor) { if (nestingCount > 0) @@ -2195,10 +2219,12 @@ namespace Spring.Objects.Factory.Support } } + CleanupAfterObjectCreationFailure(name); + hasErrors = true; if (log.IsErrorEnabled) { - log.Error(string.Format("{1}GetObjectInternal: error obtaining object {0}", name, new string(' ', nestingCount * INDENT))); + log.Error(string.Format("{1}GetObjectInternal: error obtaining object {0}", name, new string(' ', nestingCount * indent))); } throw; @@ -2217,7 +2243,7 @@ namespace Spring.Objects.Factory.Support if (log.IsDebugEnabled) { - log.Debug(string.Format("{1}GetObjectInternal: returning instance for objectname {0}", name, new string(' ', nestingCount * INDENT))); + log.Debug(string.Format("{1}GetObjectInternal: returning instance for objectname {0}", name, new string(' ', nestingCount * indent))); } } } @@ -2248,7 +2274,7 @@ namespace Spring.Objects.Factory.Support protected bool RequiresDestruction(object instance, RootObjectDefinition od) { return (instance != null && - (instance is IDisposable || od.DestroyMethodName != null || HasDestructionAwareBeanPostProcessors)); + (instance is IDisposable || od.DestroyMethodName != null || HasDestructionAwareObjectPostProcessors)); } private int nestingCount; @@ -2390,12 +2416,10 @@ namespace Spring.Objects.Factory.Support private void AfterPrototypeCreation(string name) { - var values = prototypesInCreation.Value; - if (!values.Contains(name)) + if (!prototypesInCreation.Value.Remove(name)) { ThrowNotCurrentlyInCreation(name); } - values.Remove(name); } private static void ThrowNotCurrentlyInCreation(string name) @@ -2478,11 +2502,11 @@ namespace Spring.Objects.Factory.Support } if (typeof(IInstantiationAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor)) { - hasInstantiationAwareBeanPostProcessors = true; + hasInstantiationAwareObjectPostProcessors = true; } if (typeof(IDestructionAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor)) { - hasDestructionAwareBeanPostProcessors = true; + hasDestructionAwareObjectPostProcessors = true; } } @@ -2548,7 +2572,7 @@ namespace Spring.Objects.Factory.Support /// under the given object name. /// /// . - public void RegisterSingleton(string name, object singletonObject) + public virtual void RegisterSingleton(string name, object singletonObject) { AssertUtils.ArgumentHasText(name, "name", "The singleton object cannot be registered under an empty name."); lock (GetSingletonLockFor(name)) @@ -2557,9 +2581,7 @@ namespace Spring.Objects.Factory.Support if (oldObject != null) { throw new ObjectDefinitionStoreException( - string.Format( - "Could not register object [{0}] under object name '{1}': there's already object [{2}] bound.", - singletonObject, name, oldObject)); + $"Could not register object [{singletonObject}] under object name '{name}': there's already object [{oldObject}] bound."); } AddSingleton(name, singletonObject); } @@ -2694,5 +2716,59 @@ namespace Spring.Objects.Factory.Support { return singletonLocks.GetOrAdd(objectName, key => new Lazy(() => new object())).Value; } + + [Serializable] + private class LogicalThreadContextSetVariable : IDisposable + { + private readonly string name = Guid.NewGuid().ToString(); + + public HashSet Value + { + get + { + if (!(LogicalThreadContext.GetData(name) is HashSet set)) + { + set = new HashSet(); + LogicalThreadContext.SetData(name, set); + } + return set; + } + } + + public void Dispose() + { + LogicalThreadContext.FreeNamedDataSlot(name); + } + } + + /// + /// Makes a distinction between sort order and object identity. + /// This is important when used with , since most + /// implementations assume Order == Identity + /// + [Serializable] + private class ObjectOrderComparator : OrderComparator + { + public static readonly ObjectOrderComparator ObjectOrderComparatorInstance = new ObjectOrderComparator(); + /// + /// Handle the case when both objects have equal sort order priority. By default returns 0, + /// but may be overriden for handling special cases. + /// + /// The first object to compare. + /// The second object to compare. + /// + /// -1 if first object is less then second, 1 if it is greater, or 0 if they are equal. + /// + protected override int CompareEqualOrder(object o1, object o2) + { + if (ReferenceEquals(o1, o2)) + return 0; + if (o1 == null) + return 1; + if (o2 == null) + return -1; + return o1.GetHashCode().CompareTo(o2.GetHashCode()); + } + } } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs index 3b940240..b3bf4248 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AutowireUtils.cs @@ -1,5 +1,5 @@ /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,7 +82,7 @@ namespace Spring.Objects.Factory.Support MemberInfo[] ctors = definition.ObjectType.FindMembers( MemberTypes.Constructor, flags, - new MemberFilter(new CriteriaMemberFilter().FilterMemberByCriteria), + new CriteriaMemberFilter().FilterMemberByCriteria, new MinimumArgumentCountCriteria(minimumArgumentCount)); constructors = (ConstructorInfo[]) ArrayList.Adapter(ctors).ToArray(typeof (ConstructorInfo)); } @@ -90,7 +90,7 @@ namespace Spring.Objects.Factory.Support { constructors = definition.ObjectType.GetConstructors(flags); } - AutowireUtils.SortConstructors(constructors); + SortConstructors(constructors); return constructors; } @@ -181,11 +181,11 @@ namespace Spring.Objects.Factory.Support public static int GetTypeDifferenceWeight(Type[] paramTypes, object[] args) { int result = 0; - for (int i = 0; i < paramTypes.Length; i++) + for (int i = 0; i < (uint) paramTypes.Length; i++) { if (!ObjectUtils.IsAssignable(paramTypes[i], args[i])) { - return Int32.MaxValue; + return int.MaxValue; } if (args[i] != null) { @@ -193,7 +193,7 @@ namespace Spring.Objects.Factory.Support Type superType = args[i].GetType().BaseType; while (superType != null) { - if (paramType.Equals(superType)) + if (paramType == superType) { result = result + 2; superType = null; @@ -226,7 +226,7 @@ namespace Spring.Objects.Factory.Support /// public static Boolean IsExcludedFromDependencyCheck(PropertyInfo pi) { - return (pi.GetSetMethod() == null) ? false : true; + return pi.GetSetMethod() != null; } /// @@ -245,15 +245,16 @@ namespace Spring.Objects.Factory.Support /// public static void SortConstructors(ConstructorInfo[] constructors) { - if (constructors != null - && constructors.Length > 0) + if (constructors != null && constructors.Length > 0) { - Array.Sort(constructors, new ConstructorComparer()); + Array.Sort(constructors, ConstructorComparer.Instance); } } private sealed class ConstructorComparer : IComparer - { + { + internal static readonly ConstructorComparer Instance = new ConstructorComparer(); + public int Compare(object lhs, object rhs) { ConstructorInfo lhsCtor = (ConstructorInfo) lhs; @@ -282,6 +283,8 @@ namespace Spring.Objects.Factory.Support private sealed class MinimumArgumentCountCriteria : ICriteria { + private readonly int _minimumArgumentCount; + public MinimumArgumentCountCriteria(int minimumArgumentCount) { _minimumArgumentCount = minimumArgumentCount; @@ -289,12 +292,8 @@ namespace Spring.Objects.Factory.Support public bool IsSatisfied(object datum) { - bool satisfied = false; - satisfied = ((MethodBase) datum).GetParameters().Length >= _minimumArgumentCount; - return satisfied; + return ((MethodBase) datum).GetParameters().Length >= _minimumArgumentCount; } - - private int _minimumArgumentCount; } /// diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs index c2e02bc9..86375194 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ConstructorResolver.cs @@ -114,8 +114,11 @@ namespace Spring.Objects.Factory.Support /// The explicit chose ctor args. /// A ConstructorInstantiationInfo containg the specified constructor in the RootObjectDefinition or /// one based on type matching. - public ConstructorInstantiationInfo GetConstructorInstantiationInfo(string objectName, RootObjectDefinition rod, - ConstructorInfo[] chosenCtors, object[] explicitArgs) + public ConstructorInstantiationInfo GetConstructorInstantiationInfo( + string objectName, + RootObjectDefinition rod, + ConstructorInfo[] chosenCtors, + object[] explicitArgs) { ObjectWrapper wrapper = new ObjectWrapper(); @@ -150,11 +153,9 @@ namespace Spring.Objects.Factory.Support minNrOfArgs = ResolveConstructorArguments(objectName, rod, wrapper, cargs, resolvedValues); } // Take specified constructors, if any. - ConstructorInfo[] candidates = (chosenCtors != null - ? chosenCtors - : AutowireUtils.GetConstructors(rod, 0)); + ConstructorInfo[] candidates = chosenCtors ?? AutowireUtils.GetConstructors(rod, 0); AutowireUtils.SortConstructors(candidates); - int minTypeDiffWeight = Int32.MaxValue; + int minTypeDiffWeight = int.MaxValue; for (int i = 0; i < candidates.Length; i++) { @@ -174,17 +175,24 @@ namespace Spring.Objects.Factory.Support + "in object '{1}' (hint: specify argument indexes, names, or " + "types to avoid ambiguities).", minNrOfArgs, objectName)); } - ArgumentsHolder args = null; + ArgumentsHolder args; if (resolvedValues != null) { - UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null; // Try to resolve arguments for current constructor //need to check for null as indicator of no ctor arg match instead of using exceptions for flow //control as in the Java implementation - args = CreateArgumentArray(objectName, rod, resolvedValues, wrapper, paramTypes, candidate, - autowiring, out unsatisfiedDependencyExceptionData); + args = CreateArgumentArray( + objectName, + rod, + resolvedValues, + wrapper, + paramTypes, + candidate, + autowiring, + out var unsatisfiedDependencyExceptionData); + if (args == null) { if (i == candidates.Length - 1 && constructorToUse == null) diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs index d8b73b04..8a9e142d 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/DefaultListableObjectFactory.cs @@ -16,14 +16,15 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; - +using Spring.Collections.Generic; using Spring.Core; using Spring.Core.TypeConversion; +using Spring.Expressions; using Spring.Objects.Factory.Config; using Spring.Util; -using Spring.Expressions; namespace Spring.Objects.Factory.Support { @@ -62,6 +63,37 @@ namespace Spring.Objects.Factory.Support IConfigurableListableObjectFactory, IObjectDefinitionRegistry { + + // The mapping of object depending object names, keyed by object name. + private Dictionary> dependingObjectNamesCache; + + // The mapping of object definition objects, keyed by object name. + private readonly Dictionary objectDefinitionMap; + + // List of object definition names, in registration order. + private List objectDefinitionNames = new List(256); + + // Resolver to use for checking if an object definition is an autowire candidate + private IAutowireCandidateResolver autowireCandidateResolver = AutowireUtils.CreateAutowireCandidateResolver(); + + // Dictionary from dependency type to corresponding autowired value + private readonly IDictionary resolvableDependencies = new Dictionary(); + + // map of singleton and non-singleton bean names, keyed by dependency type + private readonly ConcurrentDictionary> allObjectNamesByType = new ConcurrentDictionary>(); + + // map of singleton-only bean names, keyed by dependency type + private readonly ConcurrentDictionary> singletonObjectNamesByType = new ConcurrentDictionary>(); + + // list of names of manually registered singletons, in registration order + private volatile OrderedSet manualSingletonNames = new OrderedSet(); + + // cached array of bean definition names in case of frozen configuration + private volatile string[] frozenObjectDefinitionNames; + + // whether bean definition metadata may be cached for all beans + private volatile bool configurationFrozen; + /// /// Creates a new instance of the /// class. @@ -203,26 +235,28 @@ namespace Spring.Objects.Factory.Support if (dependingObjectNamesCache == null) { dependingObjectNamesCache = new Dictionary>(); - IList allObjectDefinitionNames = GetObjectDefinitionNames(); - foreach (string name in allObjectDefinitionNames) - { - if (ContainsObjectDefinition(name)) - { - RootObjectDefinition rod = GetMergedObjectDefinition(name, false); - if (rod.DependsOn != null) - { - foreach (var dependsOnName in rod.DependsOn) - { - if (!dependingObjectNamesCache.TryGetValue(dependsOnName, out dependingObjectNames)) - { - dependingObjectNames = new List(); - dependingObjectNamesCache.Add(dependsOnName, dependingObjectNames); - } - dependingObjectNames.Add(name); - } - } - } - } + var allObjectDefinitionNames = GetObjectDefinitionNames(); + for (var i = 0; i < allObjectDefinitionNames.Count; i++) + { + string name = allObjectDefinitionNames[i]; + if (ContainsObjectDefinition(name)) + { + RootObjectDefinition rod = GetMergedObjectDefinition(name, false); + if (rod.DependsOn != null) + { + foreach (var dependsOnName in rod.DependsOn) + { + if (!dependingObjectNamesCache.TryGetValue(dependsOnName, out dependingObjectNames)) + { + dependingObjectNames = new List(); + dependingObjectNamesCache.Add(dependsOnName, dependingObjectNames); + } + + dependingObjectNames.Add(name); + } + } + } + } } if (dependingObjectNamesCache.TryGetValue(objectName, out dependingObjectNames)) return dependingObjectNames; @@ -265,31 +299,6 @@ namespace Spring.Objects.Factory.Support return (rod.HasObjectType && checkedType.IsAssignableFrom(rod.ObjectType)); } - /// - /// The mapping of object depending object names, keyed by object name. - /// - private Dictionary> dependingObjectNamesCache; - - /// - /// The mapping of object definition objects, keyed by object name. - /// - private readonly Dictionary objectDefinitionMap; - - /// - /// List of object definition names, in registration order. - /// - private readonly List objectDefinitionNames = new List(); - - /// - /// Resolver to use for checking if an object definition is an autowire candidate - /// - private IAutowireCandidateResolver autowireCandidateResolver = AutowireUtils.CreateAutowireCandidateResolver(); - - /// - /// IDictionary from dependency type to corresponding autowired value - /// - private readonly IDictionary resolvableDependencies = new Dictionary(); - /// /// Return the number of objects defined in this registry. /// @@ -297,10 +306,7 @@ namespace Spring.Objects.Factory.Support /// The number of objects defined in this registry. /// /// - public int ObjectDefinitionCount - { - get { return objectDefinitionMap.Count; } - } + public int ObjectDefinitionCount => objectDefinitionMap.Count; /// /// Check if this registry contains a object definition with the given @@ -332,51 +338,123 @@ namespace Spring.Objects.Factory.Support /// If the object definition is invalid. /// /// - public override void RegisterObjectDefinition( - string name, IObjectDefinition objectDefinition) + public override void RegisterObjectDefinition(string name, IObjectDefinition objectDefinition) { - if (objectDefinition is AbstractObjectDefinition) + if (objectDefinition is AbstractObjectDefinition abstractObjectDefinition) { try { - ((AbstractObjectDefinition)objectDefinition).Validate(); + abstractObjectDefinition.Validate(); } catch (ObjectDefinitionValidationException ex) { throw new ObjectDefinitionStoreException( - objectDefinition.ResourceDescription, + abstractObjectDefinition.ResourceDescription, name, "Validation of object definition failed.", ex); } } - IObjectDefinition oldObjectDefinition; - if (objectDefinitionMap.TryGetValue(name, out oldObjectDefinition)) + + if (objectDefinitionMap.TryGetValue(name, out var existingDefinition)) { if (!AllowObjectDefinitionOverriding) { throw new ObjectDefinitionStoreException( - string.Format( - "Cannot register object definition [{0}] for object '{1}': there's already [{2}] bound.", - objectDefinition, name, oldObjectDefinition)); + $"Cannot register object definition [{objectDefinition}] for object '{name}': there's already [{existingDefinition}] bound."); } - else + + if (log.IsDebugEnabled) { - if (log.IsDebugEnabled) - { - log.Debug( - string.Format( - "Overriding object definition for object '{0}': replacing [{1}] with [{2}].", - name, oldObjectDefinition, objectDefinition)); - } + log.Debug( + $"Overriding object definition for object '{name}': replacing [{existingDefinition}] with [{objectDefinition}]."); } + objectDefinitionMap[name] = objectDefinition; } else { - objectDefinitionNames.Add(name); + if (HasObjectCreationStarted) + { + // Cannot modify startup-time collection elements anymore (for stable iteration) + lock (objectDefinitionMap) + { + objectDefinitionMap[name] = objectDefinition; + var updatedDefinitions = new List(objectDefinitionNames.Count + 1); + updatedDefinitions.AddRange(objectDefinitionNames); + updatedDefinitions.Add(name); + objectDefinitionNames = updatedDefinitions; + if (manualSingletonNames.Contains(name)) + { + OrderedSet updatedSingletons = new OrderedSet(manualSingletonNames); + updatedSingletons.Remove(name); + manualSingletonNames = updatedSingletons; + } + } + } + else + { + // Still in startup registration phase + objectDefinitionMap[name] = objectDefinition; + objectDefinitionNames.Add(name); + manualSingletonNames.Remove(name); + } + + frozenObjectDefinitionNames = null; + } + + + if (existingDefinition != null || ContainsSingleton(name)) + { + ResetObjectDefinition(name); } - objectDefinitionMap[name] = objectDefinition; } + + /// + /// Reset all bean definition caches for the given bean, + /// including the caches of beans that are derived from it. + /// + /// + /// Called after an existing bean definition has been replaced or removed, + /// triggering , + /// and on the + /// given bean and on all bean definitions that have the given bean as parent. + /// + /// The name of the object to reset + protected void ResetObjectDefinition(string objectName) + { + // Remove the merged bean definition for the given bean, if already created. + ClearMergedObjectDefinition(objectName); + + // Remove corresponding bean from singleton cache, if any. Shouldn't usually + // be necessary, rather just meant for overriding a context's default beans + // (e.g. the default StaticMessageSource in a StaticApplicationContext). + DestroySingleton(objectName); + + // Notify all post-processors that the specified bean definition has been reset. + for (var i = 0; i < ObjectPostProcessors.Count; i++) + { + IObjectPostProcessor processor = ObjectPostProcessors[i]; + if (processor is IMergedObjectDefinitionPostProcessor mergedObjectDefinitionPostProcessor) + { + mergedObjectDefinitionPostProcessor.ResetObjectDefinition(objectName); + } + } + + // Reset all bean definitions that have the given bean as parent (recursively). + for (var i = 0; i < objectDefinitionNames.Count; i++) + { + string bdName = objectDefinitionNames[i]; + if (objectName != bdName) + { + var bd = objectDefinitionMap[bdName]; + if (objectName == bd.ParentName) + { + ResetObjectDefinition(bdName); + } + } + } + } + /// /// Ensure that all non-lazy-init singletons are instantiated, also @@ -477,6 +555,77 @@ namespace Spring.Objects.Factory.Support } } } + + public override void ClearMetadataCache() + { + base.ClearMetadataCache(); + ClearByTypeCache(); + } + + /// + /// Remove any assumptions about by-type mappings. + /// + private void ClearByTypeCache() + { + allObjectNamesByType.Clear(); + singletonObjectNamesByType.Clear(); + } + + public void FreezeConfiguration() + { + configurationFrozen = true; + frozenObjectDefinitionNames = objectDefinitionNames.ToArray(); + } + + public bool ConfigurationFrozen => configurationFrozen; + + public override void RegisterSingleton(string beanName, object singletonObject) + { + base.RegisterSingleton(beanName, singletonObject); + + if (HasObjectCreationStarted) + { + // Cannot modify startup-time collection elements anymore (for stable iteration) + lock (objectDefinitionMap) + { + if (!objectDefinitionMap.ContainsKey(beanName)) + { + var updatedSingletons = new OrderedSet(manualSingletonNames); + updatedSingletons.Add(beanName); + manualSingletonNames = updatedSingletons; + } + } + } + else + { + // Still in startup registration phase + if (!objectDefinitionMap.ContainsKey(beanName)) + { + manualSingletonNames.Add(beanName); + } + } + + ClearByTypeCache(); + } + + protected override void DestroySingleton(string name) + { + base.DestroySingleton(name); + manualSingletonNames.Remove(name); + ClearByTypeCache(); + } + + /// + /// Determines whether the metadata for the specified object name is eligible for caching. + /// + /// Name of the bean. + /// + /// true if [is object eligible for metadata caching] [the specified bean name]; otherwise, false. + /// + protected override bool IsObjectEligibleForMetadataCaching(string beanName) + { + return (ConfigurationFrozen || base.IsObjectEligibleForMetadataCaching(beanName)); + } /// /// Return the registered @@ -523,17 +672,16 @@ namespace Spring.Objects.Factory.Support } name = TransformedObjectName(name); - IObjectDefinition definition; - if (!objectDefinitionMap.TryGetValue(name, out definition)) + if (!objectDefinitionMap.TryGetValue(name, out var definition)) { if (!includeAncestors || ParentObjectFactory == null) { return null; } - else if (ParentObjectFactory is AbstractObjectFactory) + + if (ParentObjectFactory is AbstractObjectFactory abstractObjectFactory) { - definition = - ((AbstractObjectFactory)ParentObjectFactory).GetObjectDefinition(name, includeAncestors); + definition = abstractObjectFactory.GetObjectDefinition(name, includeAncestors); } } return definition; @@ -548,7 +696,7 @@ namespace Spring.Objects.Factory.Support /// are defined. Respects any Parent-Child hierarchy the factory is participating in. /// /// - public IList GetObjectDefinitionNames() + public IReadOnlyList GetObjectDefinitionNames() { return GetObjectDefinitionNames(false); } @@ -562,20 +710,19 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this factory, if includeAncestors is true includes all /// objects defined in parent factories, or an empty array if none are defined. /// - public IList GetObjectDefinitionNames(bool includeAncestors) + public IReadOnlyList GetObjectDefinitionNames(bool includeAncestors) { - IList results = new List(objectDefinitionNames); - - var listableObjectFactory = ParentObjectFactory as IListableObjectFactory; - - if (includeAncestors && listableObjectFactory != null) + if (!includeAncestors || !(ParentObjectFactory is IListableObjectFactory listableObjectFactory)) { - foreach (var name in listableObjectFactory.GetObjectDefinitionNames(includeAncestors)) + return objectDefinitionNames; + } + + var results = new List(objectDefinitionNames); + foreach (var name in listableObjectFactory.GetObjectDefinitionNames(includeAncestors: true)) + { + if (!results.Contains(name)) { - if (!results.Contains(name)) - { - results.Add(name); - } + results.Add(name); } } @@ -626,7 +773,7 @@ namespace Spring.Objects.Factory.Support /// are defined. /// /// - public IList GetObjectNamesForType(Type type) + public IReadOnlyList GetObjectNamesForType(Type type) { return GetObjectNamesForType(type, true, true); } @@ -654,7 +801,7 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectNames() + public IReadOnlyList GetObjectNames() { return GetObjectNamesForType(typeof(T)); } @@ -680,9 +827,24 @@ namespace Spring.Objects.Factory.Support /// are defined. /// /// - public IList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) { - List objectNames = DoGetObjectNamesForType(type, includePrototypes, includeFactoryObjects); + if (!ConfigurationFrozen || type == null || !includeFactoryObjects) + { + return DoGetObjectNamesForType(type, includePrototypes, includeFactoryObjects); + } + + ConcurrentDictionary> cache = + (includePrototypes ? allObjectNamesByType : singletonObjectNamesByType); + + if (cache.TryGetValue(type, out var objectNames)) + { + return objectNames; + } + + objectNames = DoGetObjectNamesForType(type, includePrototypes, true); + cache[type] = objectNames; + return objectNames; } @@ -710,18 +872,18 @@ namespace Spring.Objects.Factory.Support /// for all object names. /// /// - /// Whether to include prototype objects too or just singletons (also applies to - /// s). + /// Whether to include prototype objects too or just singletons (also applies to + /// s). /// /// - /// Whether to include s too - /// or just normal objects. + /// Whether to include s too + /// or just normal objects. /// /// /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) { return GetObjectNamesForType(typeof(T), includePrototypes, includeFactoryObjects); } @@ -745,7 +907,7 @@ namespace Spring.Objects.Factory.Support /// If the objects could not be created. /// /// - public IDictionary GetObjectsOfType(Type type) + public IReadOnlyDictionary GetObjectsOfType(Type type) { return GetObjectsOfType(type, true, true); } @@ -777,7 +939,7 @@ namespace Spring.Objects.Factory.Support /// /// If the objects could not be created. /// - public IDictionary GetObjects() + public IReadOnlyDictionary GetObjects() { Dictionary result = new Dictionary(); DoGetObjectsOfType(typeof(T), true, true, result); @@ -808,7 +970,7 @@ namespace Spring.Objects.Factory.Support /// If any of the objects could not be created. /// /// - public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) { Dictionary result = new Dictionary(); DoGetObjectsOfType(type, includePrototypes, includeFactoryObjects, result); @@ -874,7 +1036,7 @@ namespace Spring.Objects.Factory.Support /// /// If the objects could not be created. /// - public IDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) { Dictionary result = new Dictionary(); DoGetObjectsOfType(typeof(T), includePrototypes, includeFactoryObjects, result); @@ -912,22 +1074,27 @@ namespace Spring.Objects.Factory.Support /// public override T GetObject() { - IList objectNamesForType = GetObjectNamesForType(typeof(T)); + var objectNamesForType = GetObjectNamesForType(typeof(T)); if (objectNamesForType.Count > 1) { - IList autowireCandidates = new List(); + var autowireCandidates = new List(); foreach (var objectName in objectNamesForType) { if (GetObjectDefinition(objectName).IsAutowireCandidate) + { autowireCandidates.Add(objectName); + } } + if (autowireCandidates.Count > 0) + { objectNamesForType = autowireCandidates; + } } - if ((objectNamesForType == null) || (objectNamesForType.Count == 0)) + if ((objectNamesForType == null) || objectNamesForType.Count == 0) { throw new NoSuchObjectDefinitionException(typeof(T).FullName, "Requested Type not Defined in the Context."); } @@ -936,15 +1103,14 @@ namespace Spring.Objects.Factory.Support { return (T)GetObject(objectNamesForType[0]); } - else if (objectNamesForType.Count == 0 && ParentObjectFactory != null) + + if (objectNamesForType.Count == 0 && ParentObjectFactory != null) { return ParentObjectFactory.GetObject(); } - else - { - throw new NoSuchObjectDefinitionException(typeof(T), "expected single bean but found " + - objectNamesForType.Count + ": " + StringUtils.ArrayToCommaDelimitedString(objectNamesForType)); - } + + throw new NoSuchObjectDefinitionException(typeof(T), "expected single bean but found " + + objectNamesForType.Count + ": " + StringUtils.ArrayToCommaDelimitedString(objectNamesForType)); } /// @@ -974,9 +1140,10 @@ namespace Spring.Objects.Factory.Support protected List DoGetObjectNamesForType(Type type, bool includeNonSingletons, bool allowEagerInit) { List result = new List(); - IList objectNames = GetObjectDefinitionNames(true); - foreach (string s in objectNames) + var objectNames = GetObjectDefinitionNames(true); + for (var i = 0; i < objectNames.Count; i++) { + string s = objectNames[i]; string objectName = s; if (!IsAlias(objectName)) { @@ -985,19 +1152,21 @@ namespace Spring.Objects.Factory.Support RootObjectDefinition mod = GetMergedObjectDefinition(objectName, true); // Only check object definition if it is complete if (!mod.IsAbstract && - (allowEagerInit || (mod.HasObjectType || !mod.IsLazyInit /*|| this.AllowEagerTypeLoading*/ ) && - !RequiresEagerInitForType(mod.FactoryObjectName))) + (allowEagerInit || + (mod.HasObjectType || !mod.IsLazyInit /*|| this.AllowEagerTypeLoading*/) && + !RequiresEagerInitForType(mod.FactoryObjectName))) { bool isFactoryObject = IsFactoryObject(objectName, mod); bool matchFound = - (allowEagerInit || !isFactoryObject || ContainsSingleton(objectName)) && - (includeNonSingletons || IsSingleton(objectName)) && IsTypeMatch(objectName, type); + (allowEagerInit || !isFactoryObject || ContainsSingleton(objectName)) && + (includeNonSingletons || IsSingleton(objectName)) && IsTypeMatch(objectName, type); if (!matchFound && isFactoryObject) { // in case of a FactoryObject, try to match FactoryObject instance itself next objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName); matchFound = (includeNonSingletons || mod.IsSingleton) && IsTypeMatch(objectName, type); } + if (matchFound) { result.Add(objectName); @@ -1010,6 +1179,7 @@ namespace Spring.Objects.Factory.Support { throw; } + // Probably contains a placeholder; lets ignore it for type matching purposes. if (log.IsDebugEnabled) { @@ -1022,6 +1192,7 @@ namespace Spring.Objects.Factory.Support { throw; } + // Probably contains a placeholder; lets ignore it for type matching purposes. if (log.IsDebugEnabled) { @@ -1032,29 +1203,27 @@ namespace Spring.Objects.Factory.Support } // check singletons too, to catch manually registered singletons... - IList singletonNames = GetSingletonNames(); - foreach (string s in singletonNames) + foreach (string s in manualSingletonNames) { string objectName = s; - // only check if manually registered... - if (!ContainsObjectDefinition(objectName)) + // in the case of an IFactoryObject, match the object created by the IFactoryObject... + if (IsFactoryObject(objectName)) { - // in the case of an IFactoryObject, match the object created by the IFactoryObject... - if (IsFactoryObject(objectName)) - { - if ((includeNonSingletons || IsSingleton(objectName)) && IsTypeMatch(objectName, type)) - { - result.Add(objectName); - continue; - } - objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName); - } - if (IsTypeMatch(objectName, type)) + if ((includeNonSingletons || IsSingleton(objectName)) && IsTypeMatch(objectName, type)) { result.Add(objectName); + continue; } + + objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName); + } + + if (IsTypeMatch(objectName, type)) + { + result.Add(objectName); } } + return result; } @@ -1132,7 +1301,7 @@ namespace Spring.Objects.Factory.Support return TypeConversionUtils.ConvertValueIfNecessary(type, matchingObjects.Values, null); } else if (type.IsGenericType && - (type.GetGenericTypeDefinition() == typeof(IList<>) || type.GetGenericTypeDefinition() == typeof(Spring.Collections.Generic.ISet<>) || + (type.GetGenericTypeDefinition() == typeof(IList<>) || type.GetGenericTypeDefinition() == typeof(Collections.Generic.ISet<>) || type.GetGenericTypeDefinition() == typeof(IDictionary<,>))) { var isDictionary = (type.GetGenericTypeDefinition() == typeof (IDictionary<,>)); @@ -1268,7 +1437,7 @@ namespace Spring.Objects.Factory.Support protected bool MatchesObjectName(string objectName, string candidateName) { return (candidateName != null && - (candidateName.Equals(objectName) || GetAliases(objectName).Contains(candidateName))); + (candidateName.Equals(objectName) || DoGetAliases(objectName).Contains(candidateName))); } /// @@ -1285,8 +1454,7 @@ namespace Spring.Objects.Factory.Support private Dictionary FindAutowireCandidates(string objectName, Type requiredType, DependencyDescriptor descriptor) { - IList candidateNames = - ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.Eager); + var candidateNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.Eager); var result = new Dictionary(candidateNames.Count); foreach (var entry in resolvableDependencies) diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs b/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs index cf36a6df..53ca3556 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/IObjectDefinitionRegistry.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +18,10 @@ #endregion -#region Imports - using System.Collections.Generic; using Spring.Objects.Factory.Config; -#endregion - namespace Spring.Objects.Factory.Support { /// @@ -52,16 +48,13 @@ namespace Spring.Objects.Factory.Support /// bool IsObjectNameInUse(string objectName); - /// - /// Return the number of objects defined in the registry. - /// - /// - /// The number of objects defined in the registry. - /// - int ObjectDefinitionCount - { - get; - } + /// + /// Return the number of objects defined in the registry. + /// + /// + /// The number of objects defined in the registry. + /// + int ObjectDefinitionCount { get; } /// /// Return the names of all objects defined in this registry. @@ -70,7 +63,7 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this registry, or an empty array /// if none defined /// - IList GetObjectDefinitionNames(); + IReadOnlyList GetObjectDefinitionNames(); /// /// Return the names of all objects defined in this registry. @@ -81,8 +74,7 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this registry, if includeAncestors is true it includes /// all objects in the defined parent factories, or an empty array if none defined /// - IList GetObjectDefinitionNames(bool includeAncestors); - + IReadOnlyList GetObjectDefinitionNames(bool includeAncestors); /// /// Check if this registry contains a object definition with the given name. @@ -157,7 +149,7 @@ namespace Spring.Objects.Factory.Support /// /// If there's no such object definition. /// - IList GetAliases (string name); + IReadOnlyList GetAliases (string name); /// /// Given a object name, create an alias. We typically use this method to diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/Interface1.cs b/src/Spring/Spring.Core/Objects/Factory/Support/Interface1.cs new file mode 100644 index 00000000..a498c43a --- /dev/null +++ b/src/Spring/Spring.Core/Objects/Factory/Support/Interface1.cs @@ -0,0 +1,61 @@ +#region License + +// /* +// * Copyright 2018 the original author or authors. +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// */ + +#endregion + +using System; +using Spring.Objects.Factory.Config; + +namespace Spring.Objects.Factory.Support +{ + /// + /// Post-processor callback interface for merged bean definitions at runtime. + /// implementations may implement this sub-interface in order + /// to post-process the merged bean definition (a processed copy of the original object + /// definition) that the Spring uses to create a object instance. + /// + /// + /// The method may for example introspect + /// the object definition in order to prepare some cached metadata before post-processing + /// actual instances of a object. It is also allowed to modify the object definition but + /// only for definition properties which are actually intended for concurrent + /// modification. Essentially, this only applies to operations defined on the + /// itself but not to the properties of its base classes. + /// + public interface IMergedObjectDefinitionPostProcessor : IObjectPostProcessor + { + /// + /// Post-process the given merged object definition for the specified object. + /// + /// The merged object definition for the object + /// The actual type of the managed object instance + /// The name of the object + /// + void PostProcessMergedObjectDefinition(RootObjectDefinition objectDefinition, Type objectType, string objectName); + + /// + /// A notification that the object definition for the specified name has been reset, + /// and that this post-processor should clear any metadata for the affected object. + /// + /// + /// The default implementation is empty. + /// + /// The name of the object + void ResetObjectDefinition(string objectName); + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/LookupMethodOverride.cs b/src/Spring/Spring.Core/Objects/Factory/Support/LookupMethodOverride.cs index 1ceef99b..56722776 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/LookupMethodOverride.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/LookupMethodOverride.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/MethodInjectingInstantiationStrategy.cs b/src/Spring/Spring.Core/Objects/Factory/Support/MethodInjectingInstantiationStrategy.cs index e13e53ca..60568c9d 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/MethodInjectingInstantiationStrategy.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/MethodInjectingInstantiationStrategy.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs index 38577c4c..668791eb 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionReaderUtils.cs @@ -96,7 +96,7 @@ namespace Spring.Objects.Factory.Support AssertUtils.ArgumentNotNull(registry, "registry"); registry.RegisterObjectDefinition(objectDefinition.ObjectName, objectDefinition.ObjectDefinition); - IList aliases = objectDefinition.Aliases; + var aliases = objectDefinition.Aliases; for (int i = 0; i < aliases.Count; ++i) { string alias = aliases[i]; diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs index c1e9299f..4754b88d 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/ObjectDefinitionValueResolver.cs @@ -1,5 +1,3 @@ -#region License - /* * Copyright 2002-2010 the original author or authors. * @@ -16,8 +14,6 @@ * limitations under the License. */ -#endregion - using System; using System.Collections; using System.Collections.Generic; @@ -52,7 +48,7 @@ namespace Spring.Objects.Factory.Support /// The object factory. public ObjectDefinitionValueResolver(AbstractObjectFactory objectFactory) { - this.log = LogManager.GetLogger(this.GetType()); + log = LogManager.GetLogger(GetType()); this.objectFactory = objectFactory; } @@ -349,14 +345,12 @@ namespace Spring.Objects.Factory.Support /// A reference to another object in the factory. protected virtual object ResolveReference(IObjectDefinition definition, string name, string argumentName, RuntimeObjectReference reference) { - #region Instrumentation if (log.IsDebugEnabled) { log.Debug( string.Format(CultureInfo.InvariantCulture, "Resolving reference from property '{0}' in object '{1}' to object '{2}'.", argumentName, name, reference.ObjectName)); } - #endregion try { @@ -365,9 +359,8 @@ namespace Spring.Objects.Factory.Support if (null == objectFactory.ParentObjectFactory) { throw new ObjectCreationException(definition.ResourceDescription, name, - string.Format( - "Can't resolve reference to '{0}' in parent factory: " + "no parent factory available.", - reference.ObjectName)); + $"Can't resolve reference to '{reference.ObjectName}' in parent factory: " + + "no parent factory available."); } return objectFactory.ParentObjectFactory.GetObject(reference.ObjectName); } diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs index 953f13e9..bf610f40 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/StaticListableObjectFactory.cs @@ -1,5 +1,5 @@ /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,10 +56,7 @@ namespace Spring.Objects.Factory.Support /// /// Determine whether this object factory treats object names case-sensitive or not. /// - public bool IsCaseSensitive - { - get { return true; } - } + public bool IsCaseSensitive => true; /// /// Return the number of objects defined in the factory. @@ -67,10 +64,7 @@ namespace Spring.Objects.Factory.Support /// /// The number of objects defined in the factory. /// - public int ObjectDefinitionCount - { - get { return objects.Count; } - } + public int ObjectDefinitionCount => objects.Count; /// /// Return an instance of the given object name. @@ -78,10 +72,7 @@ namespace Spring.Objects.Factory.Support /// The name of the object to return. /// The instance of the object. /// - public object this[string name] - { - get { return GetObject(name); } - } + public object this[string name] => GetObject(name); /// /// Determines whether the object with the given name matches the specified type. @@ -492,7 +483,7 @@ namespace Spring.Objects.Factory.Support /// /// If there's no such object definition. /// - public IList GetAliases(string name) + public IReadOnlyList GetAliases(string name) { return StringUtils.EmptyStrings; } @@ -545,7 +536,7 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectDefinitionNames() + public IReadOnlyList GetObjectDefinitionNames() { List names = new List(objects.Keys); return names; @@ -560,7 +551,7 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this factory, if includeAncestors is true includes all /// objects defined in parent factories, or an empty array if none are defined. /// - public IList GetObjectDefinitionNames(bool includeAncestors) + public IReadOnlyList GetObjectDefinitionNames(bool includeAncestors) { throw new NotSupportedException("StaticListableObjectFactory does not contain object definitions."); } @@ -620,7 +611,7 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectNamesForType(Type type) + public IReadOnlyList GetObjectNamesForType(Type type) { return GetObjectNamesForType(type, true, true); } @@ -648,7 +639,7 @@ namespace Spring.Objects.Factory.Support /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectNames() + public IReadOnlyList GetObjectNames() { return GetObjectNamesForType(typeof(T)); } @@ -682,7 +673,7 @@ namespace Spring.Objects.Factory.Support /// are defined. /// /// - public IList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) { bool isFactoryType = (type != null && typeof(IFactoryObject).IsAssignableFrom(type)); List matches = new List(); @@ -735,18 +726,18 @@ namespace Spring.Objects.Factory.Support /// for all object names. /// /// - /// Whether to include prototype objects too or just singletons (also applies to - /// s). + /// Whether to include prototype objects too or just singletons (also applies to + /// s). /// /// - /// Whether to include s too - /// or just normal objects. + /// Whether to include s too + /// or just normal objects. /// /// /// The names of all objects defined in this factory, or an empty array if none /// are defined. /// - public IList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) { return GetObjectNamesForType(typeof(T), includePrototypes, includeFactoryObjects); } @@ -791,7 +782,7 @@ namespace Spring.Objects.Factory.Support /// /// If the objects could not be created. /// - public IDictionary GetObjectsOfType(Type type) + public IReadOnlyDictionary GetObjectsOfType(Type type) { return GetObjectsOfType(type, true, true); } @@ -823,7 +814,7 @@ namespace Spring.Objects.Factory.Support /// /// If the objects could not be created. /// - public IDictionary GetObjects() + public IReadOnlyDictionary GetObjects() { Dictionary collector = new Dictionary(); DoGetObjectsOfType(typeof(T), true, true, collector); @@ -856,7 +847,7 @@ namespace Spring.Objects.Factory.Support /// /// If the objects could not be created. /// - public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) { Dictionary collector = new Dictionary(); DoGetObjectsOfType(type, includeFactoryObjects, includePrototypes, collector); @@ -924,7 +915,7 @@ namespace Spring.Objects.Factory.Support /// /// If the objects could not be created. /// - public IDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) { Dictionary collector = new Dictionary(); DoGetObjectsOfType(typeof(T), includeFactoryObjects, includePrototypes, collector); @@ -962,7 +953,7 @@ namespace Spring.Objects.Factory.Support /// public T GetObject() { - IList objectNamesForType = GetObjectNamesForType(typeof(T)); + var objectNamesForType = GetObjectNamesForType(typeof(T)); if ((objectNamesForType == null) || (objectNamesForType.Count == 0)) { throw new NoSuchObjectDefinitionException(typeof(T).FullName, "Requested Type not Defined in the Context."); diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs index 3561b8e3..171a89b7 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs @@ -1,5 +1,3 @@ -#region License - /* * Copyright 2002-2005 the original author or authors. * @@ -16,10 +14,6 @@ * limitations under the License. */ -#endregion - -#region Imports - using System; using System.Globalization; using System.IO; @@ -29,8 +23,6 @@ using Spring.Core.IO; using Spring.Objects.Factory.Config; using Spring.Objects.Factory.Support; -#endregion - namespace Spring.Objects.Factory.Xml { /// @@ -47,24 +39,14 @@ namespace Spring.Objects.Factory.Xml /// Rick Evans (.NET) public class DefaultObjectDefinitionDocumentReader : IObjectDefinitionDocumentReader { - #region Constants - /// /// The shared instance for this class (and derived classes). /// protected static readonly ILog log = LogManager.GetLogger(typeof(DefaultObjectDefinitionDocumentReader)); - #endregion - - #region Fields - private XmlReaderContext readerContext; - #endregion - - #region Constructor (s) / Destructor - /// /// Creates a new instance of the DefaultObjectDefinitionDocumentReader class. /// @@ -72,10 +54,6 @@ namespace Spring.Objects.Factory.Xml { } - #endregion - - #region Properties - /// /// Gets the reader context. /// @@ -85,10 +63,6 @@ namespace Spring.Objects.Factory.Xml get { return readerContext; } } - #endregion - - #region Methods - /// /// Read object definitions from the given DOM element, and register /// them with the given object registry. @@ -109,15 +83,11 @@ namespace Spring.Objects.Factory.Xml this.readerContext = readerContext; - #region Instrumentation - if (log.IsDebugEnabled) { log.Debug("Loading object definitions."); } - #endregion - XmlElement root = doc.DocumentElement; ObjectDefinitionParserHelper parserHelper = CreateHelper(readerContext, root); @@ -129,18 +99,11 @@ namespace Spring.Objects.Factory.Xml PostProcessXml(root); - #region Instrumentation - if (log.IsDebugEnabled) { log.Debug( - string.Format( - "Found {0} <{1}> elements defining objects.", - readerContext.Registry.ObjectDefinitionCount, - ObjectDefinitionConstants.ObjectElement)); + $"Found {readerContext.Registry.ObjectDefinitionCount} <{ObjectDefinitionConstants.ObjectElement}> elements defining objects."); } - - #endregion } /// @@ -153,101 +116,97 @@ namespace Spring.Objects.Factory.Xml /// in case an error happens during parsing and registering object definitions /// protected virtual void ParseObjectDefinitions(XmlElement root, ObjectDefinitionParserHelper helper) - { - if (helper.IsDefaultNamespace(root.NamespaceURI)) - { - foreach (XmlNode node in root.ChildNodes) - { - if (node.NodeType != XmlNodeType.Element) continue; - - try - { - XmlElement element = (XmlElement)node; - if (helper.IsDefaultNamespace(element.NamespaceURI)) - { - ParseDefaultElement(element, helper); - } - else - { - helper.ParseCustomElement(element); - } - } - catch (ObjectDefinitionStoreException) - { - throw; - } - catch (Exception ex) - { - helper.ReaderContext.ReportException(node, null, "Failed parsing element", ex); - } - } + { + if (helper.IsDefaultNamespace(root.NamespaceURI)) + { + foreach (XmlNode node in root.ChildNodes) + { + if (node.NodeType != XmlNodeType.Element) continue; + + try + { + XmlElement element = (XmlElement)node; + if (helper.IsDefaultNamespace(element.NamespaceURI)) + { + ParseDefaultElement(element, helper); + } + else + { + helper.ParseCustomElement(element); + } + } + catch (ObjectDefinitionStoreException) + { + throw; + } + catch (Exception ex) + { + helper.ReaderContext.ReportException(node, null, "Failed parsing element", ex); + } + } } else - { - helper.ParseCustomElement(root); + { + helper.ParseCustomElement(root); + } + } + + private void ParseDefaultElement(XmlElement element, ObjectDefinitionParserHelper helper) + { + if (element.LocalName == ObjectDefinitionConstants.ImportElement) + { + ImportObjectDefinitionResource(element); + } + else if (element.LocalName == ObjectDefinitionConstants.AliasElement) + { + ParseAlias(element, helper.ReaderContext.Registry); + } + else if (element.LocalName == ObjectDefinitionConstants.ObjectElement) + { + ProcessObjectDefinition(element, helper); + } + } + + /// + /// Process an alias element. + /// + protected virtual void ProcessAlias(XmlElement element) + { + this.ParseAlias(element, this.ReaderContext.Registry); + } + + /// + /// Process the object element + /// + protected virtual void ProcessObjectDefinition(XmlElement element, ObjectDefinitionParserHelper helper) + { + // TODO: add event handling + try + { + ObjectDefinitionHolder bdHolder = helper.ParseObjectDefinitionElement(element); + if (bdHolder == null) + { + return; + } + bdHolder = helper.DecorateObjectDefinitionIfRequired(element, bdHolder); + + if (log.IsDebugEnabled) + { + log.Debug(string.Format(CultureInfo.InvariantCulture, "Registering object definition with id '{0}'.", bdHolder.ObjectName)); + } + + ObjectDefinitionReaderUtils.RegisterObjectDefinition(bdHolder, ReaderContext.Registry); + // TODO: Send registration event. + // ReaderContext.FireComponentRegistered(new BeanComponentDefinition(bdHolder)); + } + catch (ObjectDefinitionStoreException) + { + throw; } - } - - private void ParseDefaultElement(XmlElement element, ObjectDefinitionParserHelper helper) - { - if (element.LocalName == ObjectDefinitionConstants.ImportElement) - { - ImportObjectDefinitionResource(element); - } - else if (element.LocalName == ObjectDefinitionConstants.AliasElement) - { - ParseAlias(element, helper.ReaderContext.Registry); - } - else if (element.LocalName == ObjectDefinitionConstants.ObjectElement) - { - ProcessObjectDefinition(element, helper); - } - } - - /// - /// Process an alias element. - /// - protected virtual void ProcessAlias(XmlElement element) - { - this.ParseAlias(element, this.ReaderContext.Registry); - } - - /// - /// Process the object element - /// - protected virtual void ProcessObjectDefinition(XmlElement element, ObjectDefinitionParserHelper helper) - { - // TODO: add event handling - try - { - ObjectDefinitionHolder bdHolder = helper.ParseObjectDefinitionElement(element); - if (bdHolder == null) - { - return; - } - bdHolder = helper.DecorateObjectDefinitionIfRequired(element, bdHolder); - - #region Instrumentation - - if (log.IsDebugEnabled) - { - log.Debug(string.Format(CultureInfo.InvariantCulture, "Registering object definition with id '{0}'.", bdHolder.ObjectName)); - } - - #endregion - - ObjectDefinitionReaderUtils.RegisterObjectDefinition(bdHolder, ReaderContext.Registry); - // TODO: Send registration event. - // ReaderContext.FireComponentRegistered(new BeanComponentDefinition(bdHolder)); - } - catch (ObjectDefinitionStoreException) - { - throw; - } catch (Exception ex) { throw new ObjectDefinitionStoreException( - string.Format("Failed parsing object definition '{0}'", element.OuterXml), ex); + $"Failed parsing object definition '{element.OuterXml}'", ex); } } @@ -264,8 +223,6 @@ namespace Spring.Objects.Factory.Xml string location = resource.GetAttribute(ObjectDefinitionConstants.ImportResourceAttribute); try { - #region Instrumentation - if (log.IsDebugEnabled) { log.Debug(string.Format( @@ -273,8 +230,6 @@ namespace Spring.Objects.Factory.Xml "Attempting to import object definitions from '{0}'.", location)); } - #endregion - IResource importResource = ReaderContext.Resource.CreateRelative(location); ReaderContext.Reader.LoadObjectDefinitions(importResource); } @@ -370,7 +325,5 @@ namespace Spring.Objects.Factory.Xml // { // return "There is no parser registered for namespace '" + namespaceURI + "'"; // } - - #endregion } } diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs index 1b2b3be6..cedb18b0 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectDefinitionParserHelper.cs @@ -405,7 +405,11 @@ namespace Spring.Objects.Factory.Xml /// /// This method may be used as a last resort to post-process an object definition before it gets added to the registry. /// - protected virtual ObjectDefinitionHolder CreateObjectDefinitionHolder(XmlElement element, IConfigurableObjectDefinition definition, string objectName, IList aliases) + protected virtual ObjectDefinitionHolder CreateObjectDefinitionHolder( + XmlElement element, + IConfigurableObjectDefinition definition, + string objectName, + IReadOnlyList aliases) { return new ObjectDefinitionHolder(definition, objectName, aliases); } diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ReplacedMethodOverride.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ReplacedMethodOverride.cs index 86113b86..5b47f379 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ReplacedMethodOverride.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ReplacedMethodOverride.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs b/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs index 7fb2c843..3f82baf9 100644 --- a/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs +++ b/src/Spring/Spring.Core/Objects/Support/PropertyComparator.cs @@ -1,7 +1,7 @@ #region License /* -* Copyright © 2002-2011 the original author or authors. +* Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/Spring/Spring.Core/Util/CollectionUtils.cs b/src/Spring/Spring.Core/Util/CollectionUtils.cs index f8c0069e..652906aa 100644 --- a/src/Spring/Spring.Core/Util/CollectionUtils.cs +++ b/src/Spring/Spring.Core/Util/CollectionUtils.cs @@ -1,5 +1,3 @@ -#region License - /* * Copyright © 2002-2011 the original author or authors. * @@ -16,16 +14,10 @@ * limitations under the License. */ -#endregion - -#region Imports - using System; using System.Collections; using System.Reflection; -#endregion - namespace Spring.Util { /// @@ -533,8 +525,6 @@ namespace Spring.Util } } - #region StableSort Utility Classes - private class Entry { private class EntryComparer : IComparer @@ -573,7 +563,5 @@ namespace Spring.Util Value = value; } } - - #endregion } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Util/ObjectUtils.cs b/src/Spring/Spring.Core/Util/ObjectUtils.cs index 71df73aa..7d7d1c33 100644 --- a/src/Spring/Spring.Core/Util/ObjectUtils.cs +++ b/src/Spring/Spring.Core/Util/ObjectUtils.cs @@ -303,11 +303,12 @@ namespace Spring.Util if (RemotingServices.IsTransparentProxy(obj)) { RealProxy rp = RemotingServices.GetRealProxy(obj); - if (rp is IRemotingTypeInfo) + if (rp is IRemotingTypeInfo remotingTypeInfo) { - return ((IRemotingTypeInfo) rp).CanCastTo(type, obj); + return remotingTypeInfo.CanCastTo(type, obj); } - else if (rp != null) + + if (rp != null) { type = rp.GetProxiedType(); } diff --git a/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ObjectsFactory.cs b/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ObjectsFactory.cs index 7b214ce5..353af66d 100644 --- a/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ObjectsFactory.cs +++ b/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ObjectsFactory.cs @@ -1,5 +1,5 @@ /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ namespace Spring.Data.NHibernate.Bytecode /// A reference to the created object. public object CreateInstance(Type type) { - IList namesForType = listableObjectFactory.GetObjectNamesForType(type); + var namesForType = listableObjectFactory.GetObjectNamesForType(type); return namesForType.Count > 0 ? listableObjectFactory.GetObject(namesForType[0], type) : Activator.CreateInstance(type); } @@ -57,7 +57,7 @@ namespace Spring.Data.NHibernate.Bytecode /// A reference to the created object public object CreateInstance(Type type, bool nonPublic) { - IList namesForType = listableObjectFactory.GetObjectNamesForType(type); + var namesForType = listableObjectFactory.GetObjectNamesForType(type); return namesForType.Count > 0 ? listableObjectFactory.GetObject(namesForType[0], type) : Activator.CreateInstance(type); } diff --git a/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ReflectionOptimizer.cs b/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ReflectionOptimizer.cs index a30ee705..866e6cc8 100644 --- a/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ReflectionOptimizer.cs +++ b/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/Bytecode/ReflectionOptimizer.cs @@ -1,5 +1,5 @@ /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,7 +50,7 @@ namespace Spring.Data.NHibernate.Bytecode /// The new instance. public override object CreateInstance() { - IList namesForType = listableObjectFactory.GetObjectNamesForType(mappedType); + var namesForType = listableObjectFactory.GetObjectNamesForType(mappedType); if (namesForType.Count > 0) { return listableObjectFactory.GetObject(namesForType[0], mappedType); diff --git a/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/SessionFactoryUtils.cs b/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/SessionFactoryUtils.cs index 7689a434..ec4fb4ac 100644 --- a/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/SessionFactoryUtils.cs +++ b/src/Spring/Spring.Data.NHibernate5/Data/NHibernate/SessionFactoryUtils.cs @@ -1,5 +1,5 @@ /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -670,7 +670,7 @@ namespace Spring.Data.NHibernate { Type hibCommandType = db.CreateCommand().GetType(); - IList providerNames = ctx.GetObjectNamesForType(typeof(DbProvider), true, false); + var providerNames = ctx.GetObjectNamesForType(typeof(DbProvider), true, false); string hibCommandAQN = hibCommandType.AssemblyQualifiedName; string hibCommandAQNWithoutVersion = hibCommandType.FullName + ", " + hibCommandType.Assembly.GetName().Name; foreach (string providerName in providerNames) diff --git a/src/Spring/Spring.Data/Data/Common/DbProviderFactory.cs b/src/Spring/Spring.Data/Data/Common/DbProviderFactory.cs index 263bdb09..44c230c3 100644 --- a/src/Spring/Spring.Data/Data/Common/DbProviderFactory.cs +++ b/src/Spring/Spring.Data/Data/Common/DbProviderFactory.cs @@ -1,5 +1,5 @@ /* - * Copyright © 2002-2011 the original author or authors. + * Copyright � 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,10 +128,11 @@ namespace Spring.Data.Common ctx = new XmlApplicationContext(DBPROVIDER_CONTEXTNAME, true, new string[] { DBPROVIDER_DEFAULT_RESOURCE_NAME }); } - IList dbProviderNames = ctx.GetObjectNames(); if (log.IsInfoEnabled) { - log.Info(string.Format("{0} DbProviders Available. [{1}]", dbProviderNames.Count, StringUtils.CollectionToCommaDelimitedString(dbProviderNames))); + var dbProviderNames = ctx.GetObjectNames(); + log.Info( + $"{dbProviderNames.Count} DbProviders Available. [{StringUtils.CollectionToCommaDelimitedString(dbProviderNames)}]"); } } catch (Exception e) diff --git a/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs b/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs index ad2ec806..8b1cc67e 100644 --- a/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs +++ b/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright � 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,7 +72,7 @@ namespace Spring.Messaging.Core MessageQueueFactoryObject mqfo = new MessageQueueFactoryObject(); mqfo.MessageCreatorDelegate = messageQueueCreatorDelegate; applicationContext.ObjectFactory.RegisterSingleton(messageQueueObjectName, mqfo); - IDictionary caches = applicationContext.GetObjects(); + var caches = applicationContext.GetObjects(); foreach (KeyValuePair entry in caches) { entry.Value.Insert(mqfo.Path, new MessageQueueMetadata(mqfo.RemoteQueue, mqfo.RemoteQueueIsTransactional)); diff --git a/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueMetadataCache.cs b/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueMetadataCache.cs index 0e21365e..c3f7490a 100644 --- a/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueMetadataCache.cs +++ b/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueMetadataCache.cs @@ -56,7 +56,7 @@ namespace Spring.Messaging.Core /// public void Initialize() { - IDictionary messageQueueDictionary = configurableApplicationContext.GetObjects(); + var messageQueueDictionary = configurableApplicationContext.GetObjects(); lock (itemStore.SyncRoot) { foreach (KeyValuePair entry in messageQueueDictionary) diff --git a/src/Spring/Spring.Web/Objects/Factory/Xml/WebObjectDefinitionParserHelper.cs b/src/Spring/Spring.Web/Objects/Factory/Xml/WebObjectDefinitionParserHelper.cs index 7d24d72d..dafe7f18 100644 --- a/src/Spring/Spring.Web/Objects/Factory/Xml/WebObjectDefinitionParserHelper.cs +++ b/src/Spring/Spring.Web/Objects/Factory/Xml/WebObjectDefinitionParserHelper.cs @@ -1,19 +1,19 @@ #region License -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ #endregion @@ -85,11 +85,13 @@ namespace Spring.Objects.Factory.Xml return objectName; } - protected override ObjectDefinitionHolder CreateObjectDefinitionHolder(XmlElement element, IConfigurableObjectDefinition definition, string objectName, IList aliasesArray) + protected override ObjectDefinitionHolder CreateObjectDefinitionHolder( + XmlElement element, + IConfigurableObjectDefinition definition, + string objectName, + IReadOnlyList aliasesArray) { - IWebObjectDefinition webDefinition = definition as IWebObjectDefinition; - - if (webDefinition != null) + if (definition is IWebObjectDefinition webDefinition) { if (definition.IsSingleton && element.HasAttribute(ObjectDefinitionConstants.ScopeAttribute)) diff --git a/src/Spring/Spring.Web/Web/Support/ContextMonitor.cs b/src/Spring/Spring.Web/Web/Support/ContextMonitor.cs index 1f2fc0c0..ae912239 100644 --- a/src/Spring/Spring.Web/Web/Support/ContextMonitor.cs +++ b/src/Spring/Spring.Web/Web/Support/ContextMonitor.cs @@ -59,18 +59,16 @@ namespace Spring.Web.Support RenderHeader(res.Output, context.Request.ApplicationPath); - - IConfigurableApplicationContext appContext = - WebApplicationContext.Current as IConfigurableApplicationContext; - if (appContext == null) + if (!(WebApplicationContext.Current is IConfigurableApplicationContext appContext)) { throw new InvalidOperationException( "Implementations of IApplicationContext must also implement IConfigurableApplicationContext"); } - IList names = appContext.GetObjectDefinitionNames(); - foreach (string name in names) + var names = appContext.GetObjectDefinitionNames(); + for (var i = 0; i < names.Count; i++) { + string name = names[i]; RenderObjectDefinition(res.Output, name, appContext.ObjectFactory.GetObjectDefinition(name)); } diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorTests.cs index ca9bd976..fb46b8d6 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorTests.cs @@ -55,7 +55,7 @@ namespace Spring.Aop.Framework.AutoProxy public void DefaultExclusionPrefix() { DefaultAdvisorAutoProxyCreator aapc = (DefaultAdvisorAutoProxyCreator)ObjectFactory.GetObject(ADVISOR_APC_OBJECT_NAME); - Assert.AreEqual(ADVISOR_APC_OBJECT_NAME + DefaultAdvisorAutoProxyCreator.SEPARATOR, aapc.AdvisorObjectNamePrefix); + Assert.AreEqual(ADVISOR_APC_OBJECT_NAME + DefaultAdvisorAutoProxyCreator.Separator, aapc.AdvisorObjectNamePrefix); Assert.IsFalse(aapc.UsePrefix); } diff --git a/test/Spring/Spring.Core.Tests/Context/Config/AttributeConfigObjectDefinitionParserTests.cs b/test/Spring/Spring.Core.Tests/Context/Config/AttributeConfigObjectDefinitionParserTests.cs index cc9e2154..d4f19e27 100644 --- a/test/Spring/Spring.Core.Tests/Context/Config/AttributeConfigObjectDefinitionParserTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Config/AttributeConfigObjectDefinitionParserTests.cs @@ -18,6 +18,7 @@ #endregion +using System.Linq; using NUnit.Framework; using Spring.Context.Attributes; using Spring.Context.Support; diff --git a/test/Spring/Spring.Core.Tests/Context/Config/ComponentScanObjectDefinitionParserTests.cs b/test/Spring/Spring.Core.Tests/Context/Config/ComponentScanObjectDefinitionParserTests.cs index f17b4b28..b0b150b9 100644 --- a/test/Spring/Spring.Core.Tests/Context/Config/ComponentScanObjectDefinitionParserTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Config/ComponentScanObjectDefinitionParserTests.cs @@ -18,6 +18,7 @@ #endregion +using System.Linq; using NUnit.Framework; using Spring.Context.Attributes; using Spring.Context.Support; diff --git a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs index a9e678a7..9a09d1ba 100644 --- a/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Support/ApplicationObjectSupportTests.cs @@ -1,7 +1,5 @@ -#region License - /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +14,6 @@ * limitations under the License. */ -#endregion - -#region Imports - using System; using System.Collections.Generic; using System.Globalization; @@ -28,8 +22,6 @@ using Spring.Core.IO; using Spring.Objects.Factory; using Spring.Objects.Factory.Config; -#endregion - namespace Spring.Context.Support { [TestFixture] @@ -47,20 +39,14 @@ namespace Spring.Context.Support { } - protected override Type RequiredType - { - get { return typeof (MockApplicationContext); } - } + protected override Type RequiredType => typeof (MockApplicationContext); protected override void InitApplicationContext() { _init = true; } - public bool Init - { - get { return _init; } - } + public bool Init => _init; } internal class MyContext2 : IApplicationContext @@ -69,43 +55,25 @@ namespace Spring.Context.Support { } - #region IApplicationContext Members + public IApplicationContext ParentContext => null; - public IApplicationContext ParentContext - { - get { return null; } - set - { - } - } - - public DateTime StartupDate - { - get { return new DateTime(); } - } + public DateTime StartupDate => new DateTime(); #pragma warning disable 67 public event ApplicationEventHandler ContextEvent; #pragma warning restore 67 - public long StartupDateMilliseconds - { - get { return 0; } - } + public long StartupDateMilliseconds => 0; public string Name { - get { return AbstractApplicationContext.DefaultRootContextName; } + get => AbstractApplicationContext.DefaultRootContextName; set { } } - #endregion - - #region IListableObjectFactory Members - - public IObjectDefinition GetObjectDefinition(string name) + public IObjectDefinition GetObjectDefinition(string name) { return null; } @@ -115,7 +83,7 @@ namespace Spring.Context.Support return null; } - public IList GetObjectDefinitionNames(bool includeAncestors) + public IReadOnlyList GetObjectDefinitionNames(bool includeAncestors) { return null; } @@ -125,47 +93,47 @@ namespace Spring.Context.Support return null; } - public IList GetObjectNamesForType(Type type) + public IReadOnlyList GetObjectNamesForType(Type type) { return null; } - public IList GetObjectNames() + public IReadOnlyList GetObjectNames() { return null; } - public IList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNamesForType(Type type, bool includePrototypes, bool includeFactoryObjects) { return null; } - public IList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyList GetObjectNames(bool includePrototypes, bool includeFactoryObjects) { return null; } - IList IListableObjectFactory.GetObjectDefinitionNames() + IReadOnlyList IListableObjectFactory.GetObjectDefinitionNames() { return null; } - public IDictionary GetObjectsOfType(Type type) + public IReadOnlyDictionary GetObjectsOfType(Type type) { return null; } - public IDictionary GetObjects() + public IReadOnlyDictionary GetObjects() { return null; } - public IDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyDictionary GetObjectsOfType(Type type, bool includePrototypes, bool includeFactoryObjects) { return null; } - public IDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) + public IReadOnlyDictionary GetObjects(bool includePrototypes, bool includeFactoryObjects) { return null; } @@ -175,36 +143,23 @@ namespace Spring.Context.Support throw new NotImplementedException(); } - public int ObjectDefinitionCount - { - get { return 0; } - } + public int ObjectDefinitionCount => 0; public bool ContainsObjectDefinition(string name) { return false; } - #endregion + public bool IsCaseSensitive => true; - #region IObjectFactory Members - - public bool IsCaseSensitive - { - get { return true; } - } - - public object this[string name] - { - get { return null; } - } + public object this[string name] => null; public bool ContainsObject(string name) { return false; } - public IList GetAliases(string name) + public IReadOnlyList GetAliases(string name) { return null; } @@ -291,24 +246,13 @@ namespace Spring.Context.Support return null; } - #endregion + public IObjectFactory ParentObjectFactory => null; - #region IHierarchicalObjectFactory Members - - public IObjectFactory ParentObjectFactory - { - get { return null; } - } - - public bool ContainsLocalObject(string name) + public bool ContainsLocalObject(string name) { return false; } - #endregion - - #region IMessageSource Members - public string GetMessage(IMessageSourceResolvable resolvable, CultureInfo culture) { return null; @@ -353,19 +297,11 @@ namespace Spring.Context.Support { } - #endregion - - #region IResourceLoader Members - public IResource GetResource(string location) { return null; } - #endregion - - #region IEventRepository Members - public void PublishEvents(object sourceObject) { throw new NotImplementedException(); @@ -392,8 +328,6 @@ namespace Spring.Context.Support throw new NotImplementedException(); } - #endregion - public void PublishEvent(object sender, ApplicationEventArgs e) { throw new NotImplementedException(); @@ -422,10 +356,7 @@ namespace Spring.Context.Support _init = true; } - public bool Init - { - get { return _init; } - } + public bool Init => _init; } diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs index 15d70b9e..bf5a9332 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractListableObjectFactoryTests.cs @@ -22,21 +22,20 @@ using System; using System.Collections.Generic; - using NUnit.Framework; #endregion -namespace Spring.Objects.Factory { - - /// - /// Unit tests for the AbstractListableObjectFactory class. +namespace Spring.Objects.Factory +{ + /// + /// Unit tests for the AbstractListableObjectFactory class. /// /// Rod Johnson /// Rick Evans (.NET) public abstract class AbstractListableObjectFactoryTests : - AbstractObjectFactoryTests { - + AbstractObjectFactoryTests + { /// /// Subclasses must initialize this (via the derived ObjectFactory property). /// @@ -46,73 +45,70 @@ namespace Spring.Objects.Factory { { if (!(ObjectFactory is IListableObjectFactory)) { - throw new SystemException ("IListableObjectFactory required..."); + throw new SystemException("IListableObjectFactory required..."); } + return (IListableObjectFactory) ObjectFactory; - } + } } /// /// Subclasses can override this. /// [Test] - public virtual void Count () + public virtual void Count() { - AssertCount (19); + AssertCount(19); } - - protected internal void AssertCount (int count) + + protected internal void AssertCount(int count) { - IList defnames = ListableObjectFactory.GetObjectDefinitionNames(true); - Assert.IsTrue ( + var defnames = ListableObjectFactory.GetObjectDefinitionNames(true); + Assert.IsTrue( defnames.Count == count, - string.Format ("We should have {0} objects, not {1}.", count, defnames.Count)); + $"We should have {count} objects, not {defnames.Count}."); } - + [Test] - public virtual void ObjectCount () + public virtual void ObjectCount() { - AssertTestObjectCount (12); + AssertTestObjectCount(12); } - - public virtual void AssertTestObjectCount (int count) + + public virtual void AssertTestObjectCount(int count) { - IList defnames = - ListableObjectFactory.GetObjectNamesForType(typeof (TestObject)); - Assert.IsTrue ( + var defnames = ListableObjectFactory.GetObjectNamesForType(typeof(TestObject)); + Assert.IsTrue( defnames.Count == count, - string.Format ("We should have {0} objects for class {1}, not {2}.", count, typeof (TestObject).FullName, defnames.Count)); + $"We should have {count} objects for class {typeof(TestObject).FullName}, not {defnames.Count}."); } - + [Test] - public virtual void GetDefinitionsForNoSuchClass () + public virtual void GetDefinitionsForNoSuchClass() { - IList defnames = - ListableObjectFactory.GetObjectNamesForType (typeof (string)); - Assert.IsTrue (defnames.Count == 0, "No string definitions"); + var defnames = ListableObjectFactory.GetObjectNamesForType(typeof(string)); + Assert.IsTrue(defnames.Count == 0, "No string definitions"); } - + /// /// Check that count refers to factory class, not /// object class (we don't know what type factories may return, /// and it may even change over time). /// [Test] - public virtual void GetCountForFactoryClass () + public virtual void GetCountForFactoryClass() { - int count = - ListableObjectFactory.GetObjectNamesForType ( - typeof (IFactoryObject)).Count; - Assert.IsTrue ( + int count = ListableObjectFactory.GetObjectNamesForType(typeof(IFactoryObject)).Count; + Assert.IsTrue( count == 2, - string.Format ("Should have 2 factories, not {0}.", count)); + $"Should have 2 factories, not {count}."); } - + [Test] - public virtual void ContainsObjectDefinition () + public virtual void ContainsObjectDefinition() { - Assert.IsTrue (ListableObjectFactory.ContainsObjectDefinition ("rod")); - Assert.IsTrue (ListableObjectFactory.ContainsObjectDefinition ("roderick")); + Assert.IsTrue(ListableObjectFactory.ContainsObjectDefinition("rod")); + Assert.IsTrue(ListableObjectFactory.ContainsObjectDefinition("roderick")); } - } + } } diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryPerfTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryPerfTests.cs index b158b684..09e6259a 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryPerfTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryPerfTests.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs index e87214b5..c888d3be 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/DefaultListableObjectFactoryTests.cs @@ -1,5 +1,3 @@ -#region License - /* * Copyright 2004 the original author or authors. * @@ -16,12 +14,11 @@ * limitations under the License. */ -#endregion - using System; using System.Collections; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Reflection; using System.Runtime.Serialization; using NUnit.Framework; @@ -139,7 +136,7 @@ namespace Spring.Objects.Factory def.FactoryMethodName = "CreateTestObject"; DefaultListableObjectFactory lof = new DefaultListableObjectFactory(); lof.RegisterObjectDefinition("factoryObject", def); - IDictionary objs = lof.GetObjects(); + var objs = lof.GetObjects(); Assert.AreEqual(1, objs.Count); } @@ -153,7 +150,7 @@ namespace Spring.Objects.Factory DefaultListableObjectFactory lof = new DefaultListableObjectFactory(); lof.RegisterObjectDefinition("factoryObject", def); lof.RegisterObjectDefinition("target", new RootObjectDefinition(typeof(TestObjectCreator))); - IDictionary objs = lof.GetObjects(); + var objs = lof.GetObjects(); Assert.AreEqual(1, objs.Count); } @@ -165,7 +162,7 @@ namespace Spring.Objects.Factory = new RootObjectDefinition(typeof(TestGenericObject)); def.FactoryMethodName = "CreateList"; lof.RegisterObjectDefinition("foo", def); - IDictionary objs = lof.GetObjectsOfType(typeof(List)); + var objs = lof.GetObjectsOfType(typeof(List)); Assert.AreEqual(1, objs.Count); } @@ -179,7 +176,7 @@ namespace Spring.Objects.Factory DefaultListableObjectFactory lof = new DefaultListableObjectFactory(); lof.RegisterObjectDefinition("factoryObject", def); lof.RegisterObjectDefinition("target", new RootObjectDefinition(typeof(TestGenericObject))); - IDictionary objs = lof.GetObjectsOfType(typeof(TestGenericObject)); + var objs = lof.GetObjectsOfType(typeof(TestGenericObject)); Assert.AreEqual(1, objs.Count); } @@ -217,7 +214,7 @@ namespace Spring.Objects.Factory typeof(StaticFactoryMethodObject)); def.FactoryMethodName = "CreateObject"; lof.RegisterObjectDefinition("foo", def); - IDictionary objs = lof.GetObjectsOfType(typeof(DBNull)); + var objs = lof.GetObjectsOfType(typeof(DBNull)); Assert.AreEqual(1, objs.Count, "Must be looking at the RETURN TYPE of the factory method, " + "and hence get one DBNull object back."); @@ -394,15 +391,11 @@ namespace Spring.Objects.Factory return true; } - #region IInstantiationAwareObjectPostProcessor Members - public IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, IList pis, object objectInstance, string objectName) { return pvs; } - #endregion - public object PostProcessAfterInitialization(object obj, string objectName) { return obj; @@ -444,15 +437,11 @@ namespace Spring.Objects.Factory return true; } - #region IInstantiationAwareObjectPostProcessor Members - public IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, IList pis, object objectInstance, string objectName) { return pvs; } - #endregion - public object PostProcessAfterInitialization(object obj, string objectName) { throw new NotImplementedException(); @@ -582,7 +571,7 @@ namespace Spring.Objects.Factory TestObject test = (TestObject)lof.GetObject("test"); Assert.AreEqual(singletonObject, lof.GetObject("singletonObject")); Assert.AreEqual(singletonObject, test.Spouse); - IDictionary objectsOfType = lof.GetObjectsOfType(typeof(TestObject), false, true); + var objectsOfType = lof.GetObjectsOfType(typeof(TestObject), false, true); Assert.AreEqual(2, objectsOfType.Count); Assert.IsTrue(objectsOfType.Values.Contains(test)); Assert.IsTrue(objectsOfType.Values.Contains(singletonObject)); @@ -1450,7 +1439,7 @@ namespace Spring.Objects.Factory { TestObject instance = new TestObject(); DefaultListableObjectFactory fac = new DefaultListableObjectFactory(); - Assert.Throws(() => fac.ConfigureObject(instance, null)); + Assert.Throws(() => fac.ConfigureObject(instance, null)); } [Test] @@ -1663,8 +1652,6 @@ namespace Spring.Objects.Factory Assert.AreSame(testObject, resultObject); } - #region TestObjectPostProcessor - private class TestObjectPostProcessor : IObjectPostProcessor { private object other; @@ -1685,9 +1672,6 @@ namespace Spring.Objects.Factory } } - - #endregion - [Test] public void ConfigureObjectAppliesObjectPostProcessorsUsingDefinition() { @@ -1724,8 +1708,6 @@ namespace Spring.Objects.Factory Assert.IsNotNull(c); } - #region GetObjectNamesForTypeFindsFactoryObjects - private class A : IFactoryObject, ISerializable { public object GetObject() @@ -1749,8 +1731,6 @@ namespace Spring.Objects.Factory } } - #endregion - [Test] public void GetObjectDefinitionNamesOnlyFromChild() { @@ -1817,13 +1797,56 @@ namespace Spring.Objects.Factory DefaultListableObjectFactory of = new DefaultListableObjectFactory(); of.RegisterObjectDefinition("mod", new RootObjectDefinition(typeof(A))); - IList names = of.GetObjectNamesForType(typeof (ISerializable), false, false); + var names = of.GetObjectNamesForType(typeof (ISerializable), false, false); Assert.IsNotEmpty((ICollection) names); Assert.AreEqual("&mod", names[0]); } + + [Test, MaxTime(1000)] + public void TestRegistrationOfManyBeanDefinitionsIsFastEnough() + { + var bf = new DefaultListableObjectFactory(); + bf.RegisterObjectDefinition("b", new RootObjectDefinition(typeof(B))); + + for (int i = 0; i < 100_000; i++) { + bf.RegisterObjectDefinition("a" + i, new RootObjectDefinition(typeof(A))); + } + } - #region Helper Classes + [Test, MaxTime(1000)] + public void TestRegistrationOfManySingletonsIsFastEnough() + { + // Assume.group(TestGroup.PERFORMANCE); + var bf = new DefaultListableObjectFactory(); + bf.RegisterObjectDefinition("b", new RootObjectDefinition(typeof(B))); + // bf.getBean("b"); + for (int i = 0; i < 100000; i++) { + bf.RegisterSingleton("a" + i, new A()); + } + } + + [Test, MaxTime(3000)] + public void TestPrototypeCreationIsFastEnough() + { + var lbf = new DefaultListableObjectFactory(); + var rbd = new RootObjectDefinition(typeof(TestObject)) + { + Scope = "prototype" + }; + lbf.RegisterObjectDefinition("test", rbd); + //lbf.FreezeConfiguration(); + + for (int i = 0; i < 100_000; i++) + { + lbf.GetObject("test"); + } + } + + public class B + { + } + public interface IParent { @@ -1928,8 +1951,6 @@ namespace Spring.Objects.Factory InitWasCalled = true; } } - - #endregion } public class Foo diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs index 88ebb509..2547840e 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtilsTests.cs @@ -22,6 +22,7 @@ using System.Collections; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using Spring.Objects.Factory.Config; @@ -68,14 +69,14 @@ namespace Spring.Objects.Factory [Test] public void ObjectNamesIncludingAncestors() { - IList names = ObjectFactoryUtils.ObjectNamesIncludingAncestors(_factory); + var names = ObjectFactoryUtils.ObjectNamesIncludingAncestors(_factory); Assert.AreEqual(6, names.Count); } [Test] public void ObjectNamesForTypeIncludingAncestors() { - IList names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_factory, typeof(ITestObject)); + var names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_factory, typeof(ITestObject)); // includes 2 TestObjects from IFactoryObjects (DummyFactory definitions) Assert.AreEqual(4, names.Count); Assert.IsTrue(names.Contains("test")); @@ -92,7 +93,7 @@ namespace Spring.Objects.Factory DefaultListableObjectFactory child = new DefaultListableObjectFactory(root); child.RegisterObjectDefinition("excludeLocalObject", new RootObjectDefinition(typeof(Hashtable))); - IList names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(child, typeof(ArrayList)); + var names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(child, typeof(ArrayList)); // "excludeLocalObject" matches on the parent, but not the local object definition Assert.AreEqual(0, names.Count); diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtils_PreserveOrderInHierarchy_Tests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtils_PreserveOrderInHierarchy_Tests.cs index 13449bfe..78a7179d 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtils_PreserveOrderInHierarchy_Tests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/ObjectFactoryUtils_PreserveOrderInHierarchy_Tests.cs @@ -35,7 +35,7 @@ namespace Spring.Objects.Factory [Test] public void ObjectNamesIncludingAncestorsPreserveOrderOfRegistration() { - IList names = ObjectFactoryUtils.ObjectNamesIncludingAncestors(_factory); + var names = ObjectFactoryUtils.ObjectNamesIncludingAncestors(_factory); Assert.AreEqual(5, names.Count); Assert.AreEqual(new string[] { "objA", "objB", "objC", "obj2A", "obj2C" }, names); } @@ -43,7 +43,7 @@ namespace Spring.Objects.Factory [Test] public void ObjectNamesForTypeIncludingAncestorsPreserveOrderOfRegistration() { - IList names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_factory, _expectedtype); + var names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_factory, _expectedtype); Assert.AreEqual(5, names.Count); Assert.AreEqual(new string[] { "objA", "objB", "objC", "obj2A", "obj2C" }, names); } @@ -51,7 +51,7 @@ namespace Spring.Objects.Factory [Test] public void ObjectNamesForTypeIncludingAncestorsPrototypesAndFactoryObjectsPreserveOrderOfRegistration() { - IList names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_factory, _expectedtype, false, false); + var names = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_factory, _expectedtype, false, false); Assert.AreEqual(5, names.Count); Assert.AreEqual(new string[] { "objA", "objB", "objC", "obj2A", "obj2C" }, names); } diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ObjectDefinitionReaderUtilsTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ObjectDefinitionReaderUtilsTests.cs index 39629e72..63a4c65e 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ObjectDefinitionReaderUtilsTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Support/ObjectDefinitionReaderUtilsTests.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright © 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs index 87787773..eb684469 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectCollectionTests.cs @@ -22,6 +22,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using Common.Logging; using Common.Logging.Simple; @@ -195,12 +196,12 @@ namespace Spring.Objects.Factory.Xml { IResource resource = new ReadOnlyXmlTestResource("collections.xml", GetType()); XmlObjectFactory xof = new XmlObjectFactory(resource); - IList objectNames = xof.GetObjectDefinitionNames(); + var objectNames = xof.GetObjectDefinitionNames(); TestObject tb1 = (TestObject) xof.GetObject("aliased"); TestObject alias1 = (TestObject) xof.GetObject("myalias"); Assert.IsTrue(tb1 == alias1); - IList tb1Aliases = xof.GetAliases("aliased"); + var tb1Aliases = xof.GetAliases("aliased"); Assert.AreEqual(1, tb1Aliases.Count); Assert.IsTrue(tb1Aliases.Contains("myalias")); Assert.IsTrue(objectNames.Contains("aliased")); @@ -211,7 +212,7 @@ namespace Spring.Objects.Factory.Xml TestObject alias3 = (TestObject) xof.GetObject("alias2"); Assert.IsTrue(tb2 == alias2); Assert.IsTrue(tb2 == alias3); - IList tb2Aliases = xof.GetAliases("multiAliased"); + var tb2Aliases = xof.GetAliases("multiAliased"); Assert.AreEqual(2, tb2Aliases.Count); Assert.IsTrue(tb2Aliases.Contains("alias1")); Assert.IsTrue(tb2Aliases.Contains("alias2")); @@ -225,7 +226,7 @@ namespace Spring.Objects.Factory.Xml Assert.IsTrue(tb3 == alias4); Assert.IsTrue(tb3 == alias5); - IList tb3Aliases = xof.GetAliases("aliasWithoutId1"); + var tb3Aliases = xof.GetAliases("aliasWithoutId1"); Assert.AreEqual(2, tb2Aliases.Count); Assert.IsTrue(tb3Aliases.Contains("aliasWithoutId2")); Assert.IsTrue(tb3Aliases.Contains("aliasWithoutId3")); diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectFactoryTests.cs index e338cc0c..340ac1c9 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/XmlObjectFactoryTests.cs @@ -439,7 +439,7 @@ namespace Spring.Objects.Factory.Xml "; stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)); XmlObjectFactory factory = new XmlObjectFactory(new InputStreamResource(stream, string.Empty)); - IList names = factory.GetObjectDefinitionNames(); + var names = factory.GetObjectDefinitionNames(); // mmm, how is one to test this? I have no idea what the generated name is... Assert.AreEqual(2, names.Count, "Should have got two object names, one of which is autogenerated."); } @@ -765,7 +765,7 @@ namespace Spring.Objects.Factory.Xml // abstract objects should not match //TODO add overloaded GetObjectOfType with 1 arg - IDictionary tbs = parent.GetObjectsOfType(typeof(TestObject), true, true); + var tbs = parent.GetObjectsOfType(typeof(TestObject), true, true); Assert.AreEqual(2, tbs.Count); Assert.IsTrue(tbs.ContainsKey("inheritedTestObjectPrototype")); Assert.IsTrue(tbs.ContainsKey("inheritedTestObjectSingleton")); diff --git a/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs b/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs index d535bac5..71b9e645 100644 --- a/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs +++ b/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs @@ -30,17 +30,14 @@ namespace Spring.Validation { private bool _wasCalled; - public bool WasCalled - { - get { return _wasCalled; } - } + public bool WasCalled => _wasCalled; - public override bool Validate(object validationContext, IDictionary contextParams, IValidationErrors errors) + public override bool Validate(object validationContext, IDictionary contextParams, + IValidationErrors errors) { _wasCalled = true; - return base.Validate (validationContext, contextParams, errors); + return base.Validate(validationContext, contextParams, errors); } - } /// @@ -49,9 +46,9 @@ namespace Spring.Validation /// Aleksandar Seovic public class TrueValidator : BaseTestValidator { - public TrueValidator() - {} + { + } /// /// Validates test object. @@ -68,7 +65,7 @@ namespace Spring.Validation { public FalseValidator() { - this.Actions.Add(new ErrorMessageAction("error", "errors")); + Actions.Add(new ErrorMessageAction("error", "errors")); } /// @@ -84,26 +81,23 @@ namespace Spring.Validation public sealed class MockObjectDefinitionRegistry : IObjectDefinitionRegistry { - private IDictionary objects = new Dictionary(); + private readonly IDictionary objects = new Dictionary(); - public int ObjectDefinitionCount + public int ObjectDefinitionCount => objects.Count; + + public IReadOnlyList GetObjectDefinitionNames() { - get { return this.objects.Count; } + return new List(objects.Keys); } - public IList GetObjectDefinitionNames() + public IReadOnlyList GetObjectDefinitionNames(bool includeAncestor) { - return new List(this.objects.Keys); - } - - public IList GetObjectDefinitionNames(bool includeAncestor) - { - return new List(this.objects.Keys); + return new List(objects.Keys); } public IList GetObjectDefinitions() { - return new List(this.objects.Values); + return new List(objects.Values); } public bool ContainsObjectDefinition(string name) @@ -113,17 +107,16 @@ namespace Spring.Validation public IObjectDefinition GetObjectDefinition(string name) { - IObjectDefinition definition; - objects.TryGetValue(name, out definition); + objects.TryGetValue(name, out var definition); return definition; } public void RegisterObjectDefinition(string name, IObjectDefinition definition) { - this.objects[name] = definition; + objects[name] = definition; } - public IList GetAliases(string name) + public IReadOnlyList GetAliases(string name) { throw new NotImplementedException(); } @@ -135,8 +128,7 @@ namespace Spring.Validation public bool IsObjectNameInUse(string objectName) { - return this.objects[objectName] != null; + return objects[objectName] != null; } } - } \ No newline at end of file diff --git a/test/Spring/Spring.Data.Tests/Data/Common/DbProviderFactoryTests.cs b/test/Spring/Spring.Data.Tests/Data/Common/DbProviderFactoryTests.cs index 055cc068..121ed897 100644 --- a/test/Spring/Spring.Data.Tests/Data/Common/DbProviderFactoryTests.cs +++ b/test/Spring/Spring.Data.Tests/Data/Common/DbProviderFactoryTests.cs @@ -193,7 +193,7 @@ namespace Spring.Data.Common //Initialize internal application context. factory DbProviderFactory.GetDbProvider("SqlServer-2.0"); IApplicationContext ctx = DbProviderFactory.ApplicationContext; - IList dbProviderNames = ctx.GetObjectNamesForType(typeof (IDbProvider)); + var dbProviderNames = ctx.GetObjectNamesForType(typeof (IDbProvider)); Assert.IsTrue(dbProviderNames.Count > 0); } #endif diff --git a/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Config/NmsNamespaceHandlerTests.cs b/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Config/NmsNamespaceHandlerTests.cs index 11e0b78f..0c5e941f 100644 --- a/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Config/NmsNamespaceHandlerTests.cs +++ b/test/Spring/Spring.Messaging.Nms.Tests/Messaging/Nms/Config/NmsNamespaceHandlerTests.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2011 the original author or authors. + * Copyright � 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,14 +68,14 @@ namespace Spring.Messaging.Nms.Config [Test] public void ObjectsCreated() { - IDictionary containers = ctx.GetObjects(); + var containers = ctx.GetObjects(); Assert.AreEqual(3, containers.Count); } [Test] public void ContainerConfiguration() { - IDictionary containers = ctx.GetObjects(); + var containers = ctx.GetObjects(); IConnectionFactory defaultConnectionFactory = (IConnectionFactory) ctx.GetObject(DEFAULT_CONNECTION_FACTORY); IConnectionFactory explicitConnectionFactory = (IConnectionFactory) ctx.GetObject(EXPLICIT_CONNECTION_FACTORY); diff --git a/test/Spring/Spring.Services.Tests/ServiceModel/Config/ChannelFactoryObjectDefinitionParserTests.cs b/test/Spring/Spring.Services.Tests/ServiceModel/Config/ChannelFactoryObjectDefinitionParserTests.cs index 1387d57e..699a65c3 100644 --- a/test/Spring/Spring.Services.Tests/ServiceModel/Config/ChannelFactoryObjectDefinitionParserTests.cs +++ b/test/Spring/Spring.Services.Tests/ServiceModel/Config/ChannelFactoryObjectDefinitionParserTests.cs @@ -103,7 +103,7 @@ namespace Spring.ServiceModel.Config IApplicationContext ctx = new XmlApplicationContext( ReadOnlyXmlTestResource.GetFilePath("ChannelFactoryObjectDefinitionParserTests.WithoutId.xml", this.GetType())); - IDictionary channels = ctx.GetObjects(); + var channels = ctx.GetObjects(); Assert.AreEqual(1, channels.Count); }