From: <jer...@us...> - 2008-05-17 01:25:22
|
Revision: 98 http://structuremap.svn.sourceforge.net/structuremap/?rev=98&view=rev Author: jeremydmiller Date: 2008-05-16 18:25:16 -0700 (Fri, 16 May 2008) Log Message: ----------- Putting WhatDoIHave back together, diagnostics fixes, rewrote InlineInstanceDefinitionInProfileAndMachineNodesTester, rewrote unit tests for error handling, made BuildSession cache instances Modified Paths: -------------- trunk/Source/CommonAssemblyInfo.cs trunk/Source/StructureMap/BuildSession.cs trunk/Source/StructureMap/Configuration/ConfigurationParser.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceDefaultExpression.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/ScanAssembliesExpression.cs trunk/Source/StructureMap/Configuration/DSL/Registry.cs trunk/Source/StructureMap/Configuration/FamilyParser.cs trunk/Source/StructureMap/Configuration/GraphBuilder.cs trunk/Source/StructureMap/Configuration/ProfileBuilder.cs trunk/Source/StructureMap/Configuration/StructureMapConfigurationSection.cs trunk/Source/StructureMap/Diagnostics/Tokens.cs trunk/Source/StructureMap/Graph/Constructor.cs trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs trunk/Source/StructureMap/Graph/PluginCollection.cs trunk/Source/StructureMap/Graph/PluginFamily.cs trunk/Source/StructureMap/Graph/PluginFamilyCollection.cs trunk/Source/StructureMap/Graph/PluginGraph.cs trunk/Source/StructureMap/IInstanceFactory.cs trunk/Source/StructureMap/IInstanceManager.cs trunk/Source/StructureMap/InstanceFactory.cs trunk/Source/StructureMap/InstanceManager.cs trunk/Source/StructureMap/InstanceMemento.cs trunk/Source/StructureMap/ObjectFactory.cs trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs trunk/Source/StructureMap/Pipeline/ConfiguredInstance.cs trunk/Source/StructureMap/Pipeline/ConstructorInstance.cs trunk/Source/StructureMap/Pipeline/DefaultInstance.cs trunk/Source/StructureMap/Pipeline/Instance.cs trunk/Source/StructureMap/Pipeline/LiteralInstance.cs trunk/Source/StructureMap/Pipeline/Profile.cs trunk/Source/StructureMap/Pipeline/PrototypeInstance.cs trunk/Source/StructureMap/Pipeline/ReferencedInstance.cs trunk/Source/StructureMap/Pipeline/UserControlInstance.cs trunk/Source/StructureMap/PipelineGraph.cs trunk/Source/StructureMap/PluginGraphBuilder.cs trunk/Source/StructureMap/Source/XmlNodeInstanceMemento.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap/StructureMapConfiguration.cs trunk/Source/StructureMap/StructureMapException.resx trunk/Source/StructureMap.Testing/BuildSessionTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/ConstructorExpressionTester.cs trunk/Source/StructureMap.Testing/Configuration/InlineInstanceDefinitionInProfileAndMachineNodesTester.cs trunk/Source/StructureMap.Testing/Container/ArrayConstructorTester.cs trunk/Source/StructureMap.Testing/Container/DynamicInjectionTester.cs trunk/Source/StructureMap.Testing/Container/ExceptionHandling/StructureMapExceptionTester.cs trunk/Source/StructureMap.Testing/Container/InstanceFactoryTester.cs trunk/Source/StructureMap.Testing/Container/Interceptors/TypeInterceptionTester.cs trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs trunk/Source/StructureMap.Testing/Graph/PluginGraphTester.cs trunk/Source/StructureMap.Testing/Graph/SetterInjectionTester.cs trunk/Source/StructureMap.Testing/ObjectFactoryTester.cs trunk/Source/StructureMap.Testing/Pipeline/BuildStrategiesTester.cs trunk/Source/StructureMap.Testing/Pipeline/ConfiguredInstanceTester.cs trunk/Source/StructureMap.Testing/Pipeline/DefaultInstanceTester.cs trunk/Source/StructureMap.Testing/Pipeline/InstanceTester.cs trunk/Source/StructureMap.Testing/Pipeline/LiteralInstanceTester.cs trunk/Source/StructureMap.Testing/Pipeline/ProfileManagerTester.cs trunk/Source/StructureMap.Testing/Pipeline/ProfileTester.cs trunk/Source/StructureMap.Testing/Pipeline/PrototypeInstanceTester.cs trunk/Source/StructureMap.Testing/Pipeline/ReferencedInstanceTester.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj trunk/Source/StructureMap.Testing/StructureMapConfigurationTester.cs trunk/Source/StructureMap.Testing/TestData/DataMother.cs Added Paths: ----------- trunk/Source/StructureMap/Configuration/ConfigurationParserBuilder.cs trunk/Source/StructureMap/Diagnostics/CharacterWidth.cs trunk/Source/StructureMap/Diagnostics/DividerLine.cs trunk/Source/StructureMap/Diagnostics/Line.cs trunk/Source/StructureMap/Diagnostics/TextLine.cs trunk/Source/StructureMap/Diagnostics/TextReportWriter.cs trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs trunk/Source/StructureMap/InstanceCache.cs trunk/Source/StructureMap.Testing/Configuration/ConfigurationParserBuilderTester.cs trunk/Source/StructureMap.Testing/Diagnostics/ trunk/Source/StructureMap.Testing/Diagnostics/TextReportWriterSmokeTester.cs trunk/Source/StructureMap.Testing/PipelineGraphTester.cs trunk/Source/StructureMap.Testing/TestUtility.cs Removed Paths: ------------- trunk/Source/StructureMap/Configuration/ConfigurationParserCollection.cs trunk/Source/StructureMap.Testing/Configuration/ConfigurationParserCollectionTester.cs trunk/Source/StructureMap.Testing/Container/ExceptionHandling/ExceptionTestRunner.cs trunk/Source/StructureMap.Testing/TestData/ExceptionHandlingTests.xml trunk/Source/StructureMap.Testing/TestData/InlineInstanceInProfileAndMachine.xml Modified: trunk/Source/CommonAssemblyInfo.cs =================================================================== --- trunk/Source/CommonAssemblyInfo.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/CommonAssemblyInfo.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -1,3 +1,4 @@ +using System; using System.Reflection; using System.Runtime.InteropServices; @@ -11,10 +12,11 @@ // </auto-generated> //------------------------------------------------------------------------------ -[assembly : ComVisible(false)] -[assembly : AssemblyVersion("2.5.0.0000")] -[assembly : AssemblyCopyrightAttribute("Copyright (c) 2007, Jeremy D. Miller")] -[assembly : AssemblyProductAttribute("StructureMap")] -[assembly : AssemblyCompanyAttribute("")] -[assembly : AssemblyConfigurationAttribute("release")] -[assembly : AssemblyInformationalVersionAttribute("2.5.0.0000")] \ No newline at end of file +[assembly: ComVisibleAttribute(false)] +[assembly: AssemblyVersionAttribute("2.5.0.0000")] +[assembly: AssemblyCopyrightAttribute("Copyright (c) 2007, Jeremy D. Miller")] +[assembly: AssemblyProductAttribute("StructureMap")] +[assembly: AssemblyCompanyAttribute("")] +[assembly: AssemblyConfigurationAttribute("release")] +[assembly: AssemblyInformationalVersionAttribute("2.5.0.0000")] + Modified: trunk/Source/StructureMap/BuildSession.cs =================================================================== --- trunk/Source/StructureMap/BuildSession.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/BuildSession.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using StructureMap.Graph; using StructureMap.Interceptors; using StructureMap.Pipeline; @@ -8,6 +10,7 @@ { private readonly InterceptorLibrary _interceptorLibrary; private readonly PipelineGraph _pipelineGraph; + private InstanceCache _cache = new InstanceCache(); public BuildSession(PipelineGraph pipelineGraph, InterceptorLibrary interceptorLibrary) { @@ -15,16 +18,36 @@ _interceptorLibrary = interceptorLibrary; } + public BuildSession(PluginGraph graph) + : this(new PipelineGraph(graph), graph.InterceptorLibrary) + { + + } + #region IBuildSession Members - public object CreateInstance(Type type, string name) + public object CreateInstance(Type pluginType, string name) { - return forType(type).Build(this, name); + Instance instance = forType(pluginType).FindInstance(name); + if (instance == null) + { + throw new StructureMapException(200, name, pluginType.FullName); + } + + return CreateInstance(pluginType, instance); } public object CreateInstance(Type pluginType, Instance instance) { - return forType(pluginType).Build(this, instance); + object result = _cache.Get(pluginType, instance); + + if (result == null) + { + result = forType(pluginType).Build(this, instance); + _cache.Set(pluginType, instance, result); + } + + return result; } public Array CreateInstanceArray(Type pluginType, Instance[] instances) @@ -57,7 +80,7 @@ throw new StructureMapException(202, pluginType.FullName); } - return forType(pluginType).Build(this, instance); + return CreateInstance(pluginType, instance); } public object ApplyInterception(Type pluginType, object actualValue) Modified: trunk/Source/StructureMap/Configuration/ConfigurationParser.cs =================================================================== --- trunk/Source/StructureMap/Configuration/ConfigurationParser.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/ConfigurationParser.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; +using StructureMap.Diagnostics; using StructureMap.Graph; using StructureMap.Source; @@ -11,76 +12,28 @@ { #region statics - public static ConfigurationParser[] GetParsers(XmlDocument document, string includePath) - { - XmlElement node = document.DocumentElement; - return GetParsers(node, includePath); - } - - // TODO -- Clean up. Maybe use some Lambda magic with .Net 3.5? - public static ConfigurationParser[] GetParsers(XmlNode node, string includePath) - { - string folder = string.IsNullOrEmpty(includePath) ? string.Empty : Path.GetDirectoryName(includePath); - - List<ConfigurationParser> list = new List<ConfigurationParser>(); - - list.Add(new ConfigurationParser(node)); - - string includedPath = null; - - try - { - XmlNodeList includeNodes = node.SelectNodes(XmlConstants.INCLUDE_NODE); - foreach (XmlElement includeElement in includeNodes) - { - XmlDocument includedDoc = new XmlDocument(); - string fileName = includeElement.GetAttribute("File"); - - if (fileName == string.Empty) - { - // TODO: get rid of throw, put on PluginGraph here - throw new ApplicationException("The File attribute on the Include node is required"); - } - - try - { - includedPath = Path.Combine(folder, fileName); - includedDoc.Load(includedPath); - - - ConfigurationParser parser = new ConfigurationParser(includedDoc.DocumentElement); - list.Add(parser); - } - catch (Exception ex) - { - // TODO: get rid of throw, put on PluginGraph here - throw new StructureMapException(150, ex, fileName); - } - } - } - catch (Exception ex) - { - // TODO: get rid of throw, put on PluginGraph here - throw new StructureMapException(100, includedPath, ex); - } - - return list.ToArray(); - } - - public static ConfigurationParser FromFile(string filename) { XmlDocument document = new XmlDocument(); document.Load(filename); XmlNode structureMapNode = document.SelectSingleNode("//" + XmlConstants.STRUCTUREMAP); - return new ConfigurationParser(structureMapNode); + if (structureMapNode == null) + { + throw new StructureMapException(155, filename); + } + + ConfigurationParser parser = new ConfigurationParser(structureMapNode); + parser.FilePath = filename; + + return parser; } #endregion private readonly XmlMementoCreator _mementoCreator; private readonly XmlNode _structureMapNode; + private string _filePath = string.Empty; public ConfigurationParser(XmlNode structureMapNode) { @@ -106,6 +59,36 @@ XmlConstants.KEY_ATTRIBUTE); } + public void ForEachFile(GraphLog log, Action<string> action) + { + // TODO: Clean up with 3.5 + string includePath = getIncludePath(); + XmlNodeList includeNodes = _structureMapNode.SelectNodes(XmlConstants.INCLUDE_NODE); + foreach (XmlElement includeElement in includeNodes) + { + string fileName = includeElement.GetAttribute("File"); + if (string.IsNullOrEmpty(fileName)) + { + log.RegisterError(156, _filePath); + } + else + { + string includedFile = Path.Combine(includePath, fileName); + action(includedFile); + } + } + } + + private string getIncludePath() + { + if (string.IsNullOrEmpty(_filePath)) + { + return string.Empty; + } + + return Path.GetDirectoryName(_filePath); + } + public string Id { get @@ -115,6 +98,13 @@ } } + + public string FilePath + { + get { return _filePath; } + set { _filePath = value; } + } + public void ParseAssemblies(IGraphBuilder builder) { parseAssemblies(builder); Added: trunk/Source/StructureMap/Configuration/ConfigurationParserBuilder.cs =================================================================== --- trunk/Source/StructureMap/Configuration/ConfigurationParserBuilder.cs (rev 0) +++ trunk/Source/StructureMap/Configuration/ConfigurationParserBuilder.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using StructureMap.Diagnostics; + +namespace StructureMap.Configuration +{ + public class ConfigurationParserBuilder + { + private readonly List<XmlNode> _nodes = new List<XmlNode>(); + private readonly List<string> _otherFiles = new List<string>(); + private bool _ignoreDefaultFile = false; + private readonly GraphLog _log; + private bool _useAndEnforceExistenceOfDefaultFile = false; + private bool _pullConfigurationFromAppConfig; + + + public ConfigurationParserBuilder(GraphLog log) + { + _log = log; + } + + public bool UseAndEnforceExistenceOfDefaultFile + { + get { return _useAndEnforceExistenceOfDefaultFile; } + set { _useAndEnforceExistenceOfDefaultFile = value; } + } + + + public bool IgnoreDefaultFile + { + get { return _ignoreDefaultFile; } + set { _ignoreDefaultFile = value; } + } + + public bool PullConfigurationFromAppConfig + { + get { return _pullConfigurationFromAppConfig; } + set + { + _pullConfigurationFromAppConfig = value; + } + } + + // TODO: Clean up with 3.5 + public ConfigurationParser[] GetParsers() + { + List<ConfigurationParser> list = new List<ConfigurationParser>(); + + // Pick up the configuration in the default StructureMap.config + string pathToStructureMapConfig = StructureMapConfiguration.GetStructureMapConfigurationPath(); + if (shouldUseStructureMapConfigFileAt(pathToStructureMapConfig)) + { + _log.Try(delegate() + { + ConfigurationParser parser = ConfigurationParser.FromFile(pathToStructureMapConfig); + list.Add(parser); + }).AndReportErrorAs(100, pathToStructureMapConfig); + } + + foreach (string filename in _otherFiles) + { + _log.Try(delegate() + { + ConfigurationParser parser = ConfigurationParser.FromFile(filename); + list.Add(parser); + }).AndReportErrorAs(160, filename); + } + + if (_pullConfigurationFromAppConfig) + { + _log.Try(delegate() + { + IList<XmlNode> appConfigNodes = StructureMapConfigurationSection.GetStructureMapConfiguration(); + foreach (XmlNode appConfigNode in appConfigNodes) + { + IncludeNode(appConfigNode); + } + }).AndLogAnyErrors(); + + } + + // TODO -- some error handling here, or somewhere else. Need to create ConfigurationParser + // as soon as the node is added to try to determine errors + foreach (XmlNode node in _nodes) + { + ConfigurationParser parser = new ConfigurationParser(node); + list.Add(parser); + } + + foreach (ConfigurationParser parser in list.ToArray()) + { + parser.ForEachFile(_log, + delegate(string filename) + { + _log.Try(delegate() + { + ConfigurationParser childParser = ConfigurationParser.FromFile(filename); + list.Add(childParser); + }).AndReportErrorAs(150, filename); + }); + } + + + return list.ToArray(); + } + + private bool shouldUseStructureMapConfigFileAt(string pathToStructureMapConfig) + { + return + (_useAndEnforceExistenceOfDefaultFile || + File.Exists(pathToStructureMapConfig)) && !_ignoreDefaultFile; + } + + + public void IncludeFile(string filename) + { + _otherFiles.Add(filename); + } + + public void IncludeNode(XmlNode node) + { + _nodes.Add(node); + } + + public static ConfigurationParser[] GetParsers(XmlNode node, GraphLog log) + { + ConfigurationParserBuilder builder = new ConfigurationParserBuilder(log); + builder.IncludeNode(node); + builder.IgnoreDefaultFile = true; + + return builder.GetParsers(); + } + } +} \ No newline at end of file Deleted: trunk/Source/StructureMap/Configuration/ConfigurationParserCollection.cs =================================================================== --- trunk/Source/StructureMap/Configuration/ConfigurationParserCollection.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/ConfigurationParserCollection.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Xml; - -namespace StructureMap.Configuration -{ - // TODO: 3.5 cleanup here - public delegate XmlNode FetchNodeDelegate(); - - public class ConfigurationParserCollection - { - private readonly List<FetchNodeDelegate> _fetchers = new List<FetchNodeDelegate>(); - private readonly List<string> _otherFiles = new List<string>(); - private bool _ignoreDefaultFile = false; - private bool _useAndEnforceExistenceOfDefaultFile = false; - - public bool UseAndEnforceExistenceOfDefaultFile - { - get { return _useAndEnforceExistenceOfDefaultFile; } - set { _useAndEnforceExistenceOfDefaultFile = value; } - } - - - public bool IgnoreDefaultFile - { - get { return _ignoreDefaultFile; } - set { _ignoreDefaultFile = value; } - } - - public ConfigurationParser[] GetParsers() - { - List<ConfigurationParser> list = new List<ConfigurationParser>(); - - // Pick up the configuration in the default StructureMap.config - string pathToStructureMapConfig = StructureMapConfiguration.GetStructureMapConfigurationPath(); - if (shouldUseStructureMapConfigFile(pathToStructureMapConfig)) - { - addParsersFromFile(pathToStructureMapConfig, list); - } - - foreach (string file in _otherFiles) - { - addParsersFromFile(file, list); - } - - foreach (FetchNodeDelegate fetcher in _fetchers) - { - XmlNode node = fetcher(); - addParsersFromDocument(node, string.Empty, list); - } - - return list.ToArray(); - } - - private bool shouldUseStructureMapConfigFile(string pathToStructureMapConfig) - { - return - (_useAndEnforceExistenceOfDefaultFile || File.Exists(pathToStructureMapConfig)) && !_ignoreDefaultFile; - } - - private static void addParsersFromFile(string filename, List<ConfigurationParser> list) - { - try - { - XmlDocument doc = new XmlDocument(); - doc.Load(filename); - - string includePath = Path.GetDirectoryName(filename); - addParsersFromDocument(doc.DocumentElement, includePath, list); - } - catch (Exception ex) - { - // TODO -- needs to log to PluginGraph instead - throw new StructureMapException(100, filename, ex); - } - } - - private static void addParsersFromDocument(XmlNode node, string includePath, List<ConfigurationParser> list) - { - ConfigurationParser[] parsers = ConfigurationParser.GetParsers(node, includePath); - list.AddRange(parsers); - } - - public void IncludeFile(string filename) - { - _otherFiles.Add(filename); - } - - public void IncludeNode(FetchNodeDelegate fetcher) - { - _fetchers.Add(fetcher); - } - } -} \ No newline at end of file Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -37,6 +37,11 @@ #endregion // TODO: 3.5, Try alterAndContinue(f => {}); + private CreatePluginFamilyExpression<PLUGINTYPE> alterAndContinue(Action<PluginFamily> action) + { + _alterations.Add(action); + return this; + } /// <summary> /// Sets the default instance of a Type to the definition represented by builder @@ -45,21 +50,17 @@ /// <returns></returns> public CreatePluginFamilyExpression<PLUGINTYPE> TheDefaultIs(Instance instance) { - _alterations.Add(delegate(PluginFamily family) + return alterAndContinue(delegate(PluginFamily family) { family.AddInstance(instance); family.DefaultInstanceKey = instance.Name; }); - - return this; } public CreatePluginFamilyExpression<PLUGINTYPE> AddInstance(Instance instance) { - // TODO: Validate pluggability - _alterations.Add(delegate(PluginFamily family) { family.AddInstance(instance); }); - - return this; + return alterAndContinue( + delegate(PluginFamily family) { family.AddInstance(instance); }); } /// <summary> @@ -74,9 +75,9 @@ { ExpressionValidator.ValidatePluggabilityOf(typeof (CONCRETETYPE)).IntoPluginType(_pluginType); - _alterations.Add(delegate(PluginFamily family) + return alterAndContinue(delegate(PluginFamily family) { - Plugin plugin = family.Plugins.FindOrCreate(typeof (CONCRETETYPE), true); + Plugin plugin = family.Plugins.FindOrCreate(typeof(CONCRETETYPE), true); family.DefaultInstanceKey = plugin.ConcreteKey; }); @@ -91,9 +92,7 @@ /// <returns></returns> public CreatePluginFamilyExpression<PLUGINTYPE> CacheBy(InstanceScope scope) { - _alterations.Add(delegate(PluginFamily family) { family.SetScopeTo(scope); }); - - return this; + return alterAndContinue(delegate(PluginFamily family) { family.SetScopeTo(scope); }); } /// <summary> @@ -147,6 +146,8 @@ public CreatePluginFamilyExpression<PLUGINTYPE> AddConcreteType<CONCRETETYPE>(string instanceName) { + ExpressionValidator.ValidatePluggabilityOf(typeof(CONCRETETYPE)).IntoPluginType(typeof(PLUGINTYPE)); + _alterations.Add( delegate(PluginFamily family) { @@ -174,6 +175,8 @@ public CreatePluginFamilyExpression<PLUGINTYPE> AliasConcreteType<PLUGGEDTYPE>(string concreteKey) { + ExpressionValidator.ValidatePluggabilityOf(typeof(PLUGGEDTYPE)).IntoPluginType(typeof(PLUGINTYPE)); + _alterations.Add(delegate(PluginFamily family) { family.AddPlugin(typeof (PLUGGEDTYPE), concreteKey); }); return this; Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceDefaultExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceDefaultExpression.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceDefaultExpression.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -33,21 +33,27 @@ internal void Configure(string profileName, PluginGraph pluginGraph) { + // The profile instance is defined inline if (_instance != null) { _instanceKey = Profile.InstanceKeyForProfile(profileName); _instance.Name = _instanceKey; pluginGraph.FindFamily(_pluginType).AddInstance(_instance); } + + // Using a referenced key for the profile else if (!string.IsNullOrEmpty(_instanceKey)) { _instance = new ReferencedInstance(_instanceKey); } + // Set the default instance in the Profile if (_instance != null) { pluginGraph.ProfileManager.SetDefault(profileName, _pluginType, _instance); } + + // Blow up if the Profile expression is not complete. else { throw new StructureMapException(304, TypePath.GetAssemblyQualifiedName(_pluginType)); @@ -61,6 +67,8 @@ /// <returns></returns> public ProfileExpression Use(Instance instance) { + // TODO -- validate that the instance can be plugged into the PluginType + _instance = instance; return _parent; Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/ScanAssembliesExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/ScanAssembliesExpression.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/ScanAssembliesExpression.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -73,7 +73,6 @@ public ScanAssembliesExpression AddAllTypesOf<PLUGINTYPE>() { - // TODO: Do this by adding something to TypeScanner _registry.addExpression(delegate(PluginGraph pluginGraph) { PluginFamily family = Modified: trunk/Source/StructureMap/Configuration/DSL/Registry.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -238,9 +238,9 @@ } public static ConstructorInstance ConstructedBy<PLUGINTYPE> - (BuildObjectDelegate builder) + (Func<PLUGINTYPE> builder) { - return new ConstructorInstance(builder); + return new ConstructorInstance(delegate() { return builder(); }); } public static ReferencedInstance Instance(string referencedKey) Modified: trunk/Source/StructureMap/Configuration/FamilyParser.cs =================================================================== --- trunk/Source/StructureMap/Configuration/FamilyParser.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/FamilyParser.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -22,17 +22,17 @@ { TypePath typePath = TypePath.CreateFromXmlNode(familyElement); _builder.ConfigureFamily(typePath, delegate(PluginFamily family) - { - family.DefaultInstanceKey = - familyElement.GetAttribute(XmlConstants.DEFAULT_KEY_ATTRIBUTE); + { + family.DefaultInstanceKey = + familyElement.GetAttribute(XmlConstants.DEFAULT_KEY_ATTRIBUTE); - InstanceScope scope = findScope(familyElement); - family.SetScopeTo(scope); + InstanceScope scope = findScope(familyElement); + family.SetScopeTo(scope); - attachMementoSource(family, familyElement); - attachPlugins(family, familyElement); - attachInterceptors(family, familyElement); - }); + attachMementoSource(family, familyElement); + attachPlugins(family, familyElement); + attachInterceptors(family, familyElement); + }); } public void ParseDefaultElement(XmlElement element) @@ -40,28 +40,27 @@ TypePath pluginTypePath = new TypePath(element.GetAttribute(XmlConstants.PLUGIN_TYPE)); - _builder.ConfigureFamily(pluginTypePath, - delegate(PluginFamily family) - { - // TODO: there's a little duplication here - InstanceScope scope = findScope(element); - family.SetScopeTo(scope); + _builder.ConfigureFamily(pluginTypePath, delegate(PluginFamily family) + { + // TODO: there's a little duplication here + InstanceScope scope = findScope(element); + family.SetScopeTo(scope); - Type pluginType = family.PluginType; + Type pluginType = family.PluginType; - string name = element.GetAttribute(XmlConstants.NAME); - if (string.IsNullOrEmpty(name)) - { - name = "DefaultInstanceOf" + pluginTypePath.AssemblyQualifiedName; - } + string name = element.GetAttribute(XmlConstants.NAME); + if (string.IsNullOrEmpty(name)) + { + name = "DefaultInstanceOf" + pluginTypePath.AssemblyQualifiedName; + } - InstanceMemento memento = _mementoCreator.CreateMemento(element); - memento.InstanceKey = name; + InstanceMemento memento = _mementoCreator.CreateMemento(element); + memento.InstanceKey = name; - family.DefaultInstanceKey = name; + family.DefaultInstanceKey = name; - family.AddInstance(memento); - }); + family.AddInstance(memento); + }); } public void ParseInstanceElement(XmlElement element) @@ -69,11 +68,11 @@ TypePath pluginTypePath = new TypePath(element.GetAttribute(XmlConstants.PLUGIN_TYPE)); _builder.ConfigureFamily(pluginTypePath, delegate(PluginFamily family) - { - InstanceMemento memento = - _mementoCreator.CreateMemento(element); - family.AddInstance(memento); - }); + { + InstanceMemento memento = + _mementoCreator.CreateMemento(element); + family.AddInstance(memento); + }); } private InstanceScope findScope(XmlElement familyElement) @@ -97,7 +96,8 @@ { InstanceMemento sourceMemento = new XmlAttributeInstanceMemento(sourceNode); - string context = "MementoSource for " + TypePath.GetAssemblyQualifiedName(family.PluginType); + string context = "MementoSource for " + TypePath.GetAssemblyQualifiedName(family.PluginType) + "\n" + + sourceNode.OuterXml; _builder.WithSystemObject<MementoSource>(sourceMemento, context, delegate(MementoSource source) { family.AddMementoSource(source); }); } @@ -109,24 +109,29 @@ XmlNodeList pluginNodes = familyElement.SelectNodes(XmlConstants.PLUGIN_NODE); foreach (XmlElement pluginElement in pluginNodes) { - TypePath pluginPath = TypePath.CreateFromXmlNode(pluginElement); - string concreteKey = pluginElement.GetAttribute(XmlConstants.CONCRETE_KEY_ATTRIBUTE); + attachPlugin(pluginElement, family); + } + } - string context = "creating a Plugin for " + family.PluginType.AssemblyQualifiedName; - _builder.WithType(pluginPath, context, delegate(Type pluggedType) - { - Plugin plugin = new Plugin(pluggedType, concreteKey); - family.Plugins.Add(plugin); + private void attachPlugin(XmlElement pluginElement, PluginFamily family) + { + TypePath pluginPath = TypePath.CreateFromXmlNode(pluginElement); + string concreteKey = pluginElement.GetAttribute(XmlConstants.CONCRETE_KEY_ATTRIBUTE); - foreach ( - XmlElement setterElement in pluginElement.ChildNodes) - { - string setterName = - setterElement.GetAttribute("Name"); - plugin.Setters.Add(setterName); - } - }); - } + string context = "creating a Plugin for " + family.PluginType.AssemblyQualifiedName; + _builder.WithType(pluginPath, context, delegate(Type pluggedType) + { + Plugin plugin = new Plugin(pluggedType, concreteKey); + family.AddPlugin(plugin); + + foreach ( + XmlElement setterElement in pluginElement.ChildNodes) + { + string setterName = + setterElement.GetAttribute("Name"); + plugin.Setters.Add(setterName); + } + }); } // TODO: 3.5 lambda cleanup @@ -138,13 +143,13 @@ return; } - string context = "Creating an InstanceInterceptor for " + - TypePath.GetAssemblyQualifiedName(family.PluginType); + string contextBase = "creating an InstanceInterceptor for " + + TypePath.GetAssemblyQualifiedName(family.PluginType) + "\n"; foreach (XmlNode interceptorNode in interceptorChainNode.ChildNodes) { XmlAttributeInstanceMemento interceptorMemento = new XmlAttributeInstanceMemento(interceptorNode); - + string context = contextBase + interceptorNode.OuterXml; _builder.WithSystemObject<IBuildInterceptor>(interceptorMemento, context, delegate(IBuildInterceptor interceptor) { family.AddInterceptor(interceptor); }); } Modified: trunk/Source/StructureMap/Configuration/GraphBuilder.cs =================================================================== --- trunk/Source/StructureMap/Configuration/GraphBuilder.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/GraphBuilder.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -82,7 +82,7 @@ } catch (Exception ex) { - _pluginGraph.Log.RegisterError(103, ex, pluginTypePath.ClassName, pluginTypePath.AssemblyName); + _pluginGraph.Log.RegisterError(103, ex, pluginTypePath.AssemblyQualifiedName); } } @@ -108,6 +108,10 @@ Type type = path.FindType(); action(type); } + catch (StructureMapException ex) + { + _pluginGraph.Log.RegisterError(ex); + } catch (Exception ex) { _pluginGraph.Log.RegisterError(131, ex, path.AssemblyQualifiedName, context); Modified: trunk/Source/StructureMap/Configuration/ProfileBuilder.cs =================================================================== --- trunk/Source/StructureMap/Configuration/ProfileBuilder.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/ProfileBuilder.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -6,6 +6,18 @@ { public class ProfileBuilder : IProfileBuilder { + private static string _overriden_machine_name; + + public static void OverrideMachineName(string machineName) + { + _overriden_machine_name = machineName; + } + + public static void ResetMachineName() + { + _overriden_machine_name = string.Empty; + } + private readonly string _machineName; private readonly PluginGraph _pluginGraph; private readonly ProfileManager _profileManager; @@ -72,6 +84,11 @@ public static string GetMachineName() { + if (!string.IsNullOrEmpty(_overriden_machine_name)) + { + return _overriden_machine_name; + } + string machineName = string.Empty; try { Modified: trunk/Source/StructureMap/Configuration/StructureMapConfigurationSection.cs =================================================================== --- trunk/Source/StructureMap/Configuration/StructureMapConfigurationSection.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Configuration/StructureMapConfigurationSection.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -26,7 +26,6 @@ IList<XmlNode> nodes = ConfigurationSettings.GetConfig(XmlConstants.STRUCTUREMAP) as IList<XmlNode>; if (nodes == null) { - // TODO -- need to get this into PluginGraph instead throw new StructureMapException(105, XmlConstants.STRUCTUREMAP); } return nodes; Added: trunk/Source/StructureMap/Diagnostics/CharacterWidth.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/CharacterWidth.cs (rev 0) +++ trunk/Source/StructureMap/Diagnostics/CharacterWidth.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -0,0 +1,39 @@ +namespace StructureMap.Diagnostics +{ + internal class CharacterWidth + { + internal static CharacterWidth[] For(int count) + { + CharacterWidth[] widths = new CharacterWidth[count]; + for (int i = 0; i < widths.Length; i++) + { + widths[i] = new CharacterWidth(); + } + + return widths; + } + + private int _width = 0; + + internal void SetWidth(int width) + { + if (width > _width) + { + _width = width; + } + } + + internal void Add(int add) + { + _width += add; + } + + internal int Width + { + get + { + return _width; + } + } + } +} \ No newline at end of file Added: trunk/Source/StructureMap/Diagnostics/DividerLine.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/DividerLine.cs (rev 0) +++ trunk/Source/StructureMap/Diagnostics/DividerLine.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -0,0 +1,27 @@ +using System.IO; + +namespace StructureMap.Diagnostics +{ + internal class DividerLine : Line + { + private readonly char _character; + + internal DividerLine(char character) + { + _character = character; + } + + public void OverwriteCounts(CharacterWidth[] widths) + { + // no-op + } + + public void Write(TextWriter writer, CharacterWidth[] widths) + { + foreach (CharacterWidth width in widths) + { + writer.Write(string.Empty.PadRight(width.Width, _character)); + } + } + } +} \ No newline at end of file Added: trunk/Source/StructureMap/Diagnostics/Line.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/Line.cs (rev 0) +++ trunk/Source/StructureMap/Diagnostics/Line.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -0,0 +1,10 @@ +using System.IO; + +namespace StructureMap.Diagnostics +{ + internal interface Line + { + void OverwriteCounts(CharacterWidth[] widths); + void Write(TextWriter writer, CharacterWidth[] widths); + } +} \ No newline at end of file Added: trunk/Source/StructureMap/Diagnostics/TextLine.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/TextLine.cs (rev 0) +++ trunk/Source/StructureMap/Diagnostics/TextLine.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -0,0 +1,32 @@ +using System.IO; + +namespace StructureMap.Diagnostics +{ + internal class TextLine : Line + { + private readonly string[] _contents; + + internal TextLine(string[] contents) + { + _contents = contents; + } + + public void OverwriteCounts(CharacterWidth[] widths) + { + for (int i = 0; i < widths.Length; i++) + { + CharacterWidth width = widths[i]; + width.SetWidth(_contents[i].Length); + } + } + + public void Write(TextWriter writer, CharacterWidth[] widths) + { + for (int i = 0; i < widths.Length; i++) + { + CharacterWidth width = widths[i]; + writer.Write(_contents[i].PadRight(width.Width)); + } + } + } +} \ No newline at end of file Added: trunk/Source/StructureMap/Diagnostics/TextReportWriter.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/TextReportWriter.cs (rev 0) +++ trunk/Source/StructureMap/Diagnostics/TextReportWriter.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; + +namespace StructureMap.Diagnostics +{ + public class TextReportWriter + { + private readonly int _columnCount; + private List<Line> _lines = new List<Line>(); + + public TextReportWriter(int columnCount) + { + _columnCount = columnCount; + } + + public void AddDivider(char character) + { + _lines.Add(new DividerLine(character)); + } + + public void AddText(params string[] contents) + { + _lines.Add(new TextLine(contents)); + } + + public void Write(StringWriter writer) + { + CharacterWidth[] widths = CharacterWidth.For(_columnCount); + + foreach (Line line in _lines) + { + line.OverwriteCounts(widths); + } + + for (int i = 0; i < widths.Length - 1; i++) + { + CharacterWidth width = widths[i]; + width.Add(5); + } + + foreach (Line line in _lines) + { + writer.WriteLine(); + line.Write(writer, widths); + } + } + + public string Write() + { + StringBuilder sb = new StringBuilder(); + StringWriter writer = new StringWriter(sb); + + Write(writer); + + return sb.ToString(); + } + + public void DumpToConsole() + { + System.Console.WriteLine(Write()); + } + + public void DumpToDebug() + { + Debug.WriteLine(Write()); + } + } +} Modified: trunk/Source/StructureMap/Diagnostics/Tokens.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/Tokens.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Diagnostics/Tokens.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -6,11 +6,13 @@ namespace StructureMap.Diagnostics { + public delegate void Action(); + public class GraphLog { private readonly List<Source> _sources = new List<Source>(); private Source _currentSource; - private List<Error> _errors = new List<Error>(); + private readonly List<Error> _errors = new List<Error>(); public int ErrorCount { @@ -45,6 +47,13 @@ } + + public void RegisterError(StructureMapException ex) + { + Error error = new Error(ex); + addError(error); + } + private void addError(Error error) { error.Source = _currentSource; @@ -68,16 +77,75 @@ public void AssertHasError(int errorCode) { + string message = "No error with code " + errorCode + "\nHad errors: "; foreach (Error error in _errors) { + message += error.Code + ", "; if (error.Code == errorCode) { return; } } - throw new ApplicationException("No error with code " + errorCode); + throw new ApplicationException(message); } + + public void AssertHasNoError(int errorCode) + { + foreach (Error error in _errors) + { + if (error.Code == errorCode) + { + throw new ApplicationException("Has error " + errorCode); + } + } + } + + public TryAction Try(Action action) + { + return new TryAction(action, this); + } + + public class TryAction + { + private readonly Action _action; + private readonly GraphLog _log; + + internal TryAction(Action action, GraphLog log) + { + _action = action; + _log = log; + } + + public void AndReportErrorAs(int code, params object[] args) + { + try + { + _action(); + } + catch (Exception ex) + { + _log.RegisterError(code, ex, args); + } + } + + public void AndLogAnyErrors() + { + try + { + _action(); + } + catch (StructureMapException ex) + { + _log.RegisterError(ex); + } + catch (Exception ex) + { + _log.RegisterError(400, ex); + } + } + } + } public class Source @@ -154,13 +222,11 @@ { private readonly string _description; private readonly string _name; - private PluginType _pluginType; - public InstanceToken(string name, string description, PluginType pluginType) + public InstanceToken(string name, string description) { _name = name; _description = description; - _pluginType = pluginType; } @@ -174,12 +240,6 @@ get { return _description; } } - - public PluginType PluginType - { - get { return _pluginType; } - } - #region IEquatable<InstanceToken> Members public bool Equals(InstanceToken instanceToken) @@ -187,7 +247,6 @@ if (instanceToken == null) return false; if (!Equals(_name, instanceToken._name)) return false; if (!Equals(_description, instanceToken._description)) return false; - if (!Equals(_pluginType, instanceToken._pluginType)) return false; return true; } @@ -208,7 +267,6 @@ { int result = _name != null ? _name.GetHashCode() : 0; result = 29*result + (_description != null ? _description.GetHashCode() : 0); - result = 29*result + (_pluginType != null ? _pluginType.GetHashCode() : 0); return result; } } Added: trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs (rev 0) +++ trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Text; +using StructureMap.Graph; +using StructureMap.Pipeline; + +namespace StructureMap.Diagnostics +{ + public class WhatDoIHaveWriter : IPipelineGraphVisitor + { + private readonly PipelineGraph _graph; + private TextReportWriter _writer; + private List<Instance> _instances; + + public WhatDoIHaveWriter(PipelineGraph graph) + { + _graph = graph; + + } + + public string GetText() + { + _writer = new TextReportWriter(3); + _instances = new List<Instance>(); + + _writer.AddDivider('='); + _writer.AddText("PluginType", "Name", "Description"); + + _graph.Visit(this); + + _writer.AddDivider('='); + + return _writer.Write(); + } + + void IPipelineGraphVisitor.PluginType(Type pluginType, Instance defaultInstance) + { + _writer.AddDivider('-'); + string[] contents = new string[]{TypePath.GetAssemblyQualifiedName(pluginType), string.Empty, string.Empty}; + + if (defaultInstance != null) + { + setContents(contents, defaultInstance); + + } + + _writer.AddText(contents); + } + + private void setContents(string[] contents, Instance instance) + { + InstanceToken token = instance.CreateToken(); + contents[1] = token.Name; + contents[2] = token.Description; + + _instances.Add(instance); + } + + void IPipelineGraphVisitor.Instance(Type pluginType, Instance instance) + { + if (_instances.Contains(instance)) + { + return; + } + + string[] contents = new string[]{string.Empty, string.Empty, string.Empty}; + setContents(contents, instance); + + _writer.AddText(contents); + } + } +} Modified: trunk/Source/StructureMap/Graph/Constructor.cs =================================================================== --- trunk/Source/StructureMap/Graph/Constructor.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Graph/Constructor.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -107,5 +107,10 @@ if (IsEnum(parameterType)) visitor.EnumParameter(info); if (IsString(parameterType)) visitor.StringParameter(info); } + + public bool HasArguments() + { + return _ctor.GetParameters().Length > 0; + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs =================================================================== --- trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -91,9 +91,8 @@ public static PluginFamily CreateTemplatedClone(PluginFamily baseFamily, params Type[] templateTypes) { Type templatedType = baseFamily.PluginType.MakeGenericType(templateTypes); - PluginFamily templatedFamily = new PluginFamily(templatedType); + PluginFamily templatedFamily = new PluginFamily(templatedType, baseFamily.Parent); templatedFamily.DefaultInstanceKey = baseFamily.DefaultInstanceKey; - templatedFamily.Parent = baseFamily.Parent; templatedFamily.Policy = baseFamily.Policy.Clone(); // Add Plugins Modified: trunk/Source/StructureMap/Graph/PluginCollection.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginCollection.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Graph/PluginCollection.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -78,18 +78,6 @@ #endregion - /// <summary> - /// Adds a new Plugin by the PluggedType - /// </summary> - /// <param name="pluggedType"></param> - /// <param name="concreteKey"></param> - // TODO -- not wild about this method. - [Obsolete("Get rid of this")] - public void Add(Type pluggedType, string concreteKey) - { - Plugin plugin = new Plugin(pluggedType, concreteKey); - Add(plugin); - } public void Add(Plugin plugin) { @@ -108,9 +96,7 @@ // Reject if the PluggedType cannot be upcast to the PluginType if (!TypeRules.CanBeCast(_family.PluginType, plugin.PluggedType)) { - // TODO -- get this logged - throw new StructureMapException(114, plugin.PluggedType.FullName, - _family.PluginType.AssemblyQualifiedName); + throw new StructureMapException(104, plugin.PluggedType, _family.PluginType); } _plugins.Add(plugin.PluggedType, plugin); Modified: trunk/Source/StructureMap/Graph/PluginFamily.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginFamily.cs 2008-05-15 18:15:44 UTC (rev 97) +++ trunk/Source/StructureMap/Graph/PluginFamily.cs 2008-05-17 01:25:16 UTC (rev 98) @@ -25,7 +25,13 @@ private IBuildPolicy _policy; public PluginFamily(Type pluginType) + : this(pluginType, new PluginGraph()) { + } + + public PluginFamily(Type pluginType, PluginGraph parent) + { + _parent = parent; _pluginType = pluginType; _plugins = new PluginCollection(this); @@ -93,10 +99,15 @@ public void AddInstance(Instance instance) { + IDiagnosticInstance diagnosticInstance = instance; + if (!diagnosticInstance.CanBePartOfPluginFamily(this)) + { + _parent.Log.RegisterError(106, instance.CreateToken(), _pluginType); + } + _instances.Add(instance); } - // TODO -- eliminate this. Move to GraphBuilder, and wrap error handling around it // For testing public InstanceMemento GetMemento(string instanceKey) @@ -108,10 +119,13 @@ public void Seal() { _mementoList.ForEach(delegate(InstanceMemento memento) - { - Instance instance = memento.ReadInstance(Parent, _pluginType); - _instances.Add(instance); - }); + { + _parent.Log.Try(delegate() + { + Instance instance = memento.ReadInstance(Parent, _pluginType); + _instances.Add(instance); + }).AndLogAnyErrors(); + }); discoverImplicitInstances(); @@ -166,20 +180,26 @@ { if (!HasPlugin(pluggedType)) { - _plugins.Add(new Plugin(pluggedType)); + AddPlugin(new Plugin(pluggedType)); } } public Plugin AddPlugin(Type pluggedType, string key) { Plugin plugin = new Plugin(pluggedType, key); - _plugins.Add(plugin); +... [truncated message content] |