Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dictionary with values of other components that are lists throws exceptions #574

Closed
ni-mi opened this issue Nov 27, 2020 · 7 comments · Fixed by #575
Closed

Dictionary with values of other components that are lists throws exceptions #574

ni-mi opened this issue Nov 27, 2020 · 7 comments · Fixed by #575
Milestone

Comments

@ni-mi
Copy link
Contributor

ni-mi commented Nov 27, 2020

Dictionaries don't work with value types of lists.
For example:

    <component id="list" type="System.Collections.Generic.List`1[[System.String]]">
        <parameters>
            <collection>
                <array>
                    <item>11</item>
                    <item>22</item>
                </array>
            </collection>
        </parameters>
    </component>

    <component id="stringToListDictionary" type="System.Collections.Generic.Dictionary`2[System.String, System.Collections.Generic.List`1[[System.String]]]">
        <parameters>
            <dictionary>
                <dictionary>
                    <entry key="Key 1">${list}</entry>
                </dictionary>
            </dictionary>
        </parameters>
    </component>

In this example - stringToListDictionary while crash.
Reason for crash is that GenericListConverter is not implementing PerformConversion(string value, Type targetType) - but only PerformConversion(IConfiguration configuration, Type targetType).
GenericDictionaryConverter.ConvertConfigurationToCollection function uses DefaultConversionManager that finds the right converter - and picks the first eligble one: GenericListConverter - and calls PerformConversion(string value, Type targetType).
Using custom converter won't help since it is inserted in a list after GenericListConverter = so it won't get there before the exception.

@ni-mi
Copy link
Contributor Author

ni-mi commented Nov 27, 2020

I would consider the easy solution to be:
Modify GenericListConverter so that instead of throwing NotImplementedException at PerformConversion(string value, Type targetType), if the string value contains $ - it will Resolve that object: this.parent.Context.Kernel.Resolve like so:
return this.Context.Kernel.Resolve(value.Substring(2, value.Length-3), targetType);

@ni-mi ni-mi changed the title Dictionary with values of lists throws exceptions Dictionary with values of other components that are lists throws exceptions Nov 27, 2020
@ni-mi
Copy link
Contributor Author

ni-mi commented Nov 27, 2020

@jonorossi I would very much appreciate your help with this issue

@ni-mi
Copy link
Contributor Author

ni-mi commented Nov 29, 2020

Merge request #575 has a test and a fix for the issue for you to review @jonorossi

@jonorossi
Copy link
Member

Thanks for the pull request. Could you please include a full stack trace here where it throws the NotImplementedException, trying to see what it is doing but don't have time to pull up the code at the moment. We've got parameter syntax parsing code so it would be best to be using that.

@jonorossi
Copy link
Member

We've also got the property reference notation syntax (i.e. #{propertyName}) that should probably be handled for you rather than reimplementing this here with a few rough string manipulations.
https://github.com/castleproject/Windsor/blob/master/docs/xml-configuration-properties.md

@ni-mi
Copy link
Contributor Author

ni-mi commented Nov 30, 2020

Here is the stack trace

System.NotImplementedException : The method or operation is not implemented.
at Castle.MicroKernel.SubSystems.Conversion.GenericListConverter.PerformConversion (System.String value, System.Type targetType) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/SubSystems/Conversion/GenericListConverter.cs:46
at Castle.MicroKernel.SubSystems.Conversion.DefaultConversionManager.PerformConversion (System.String value, System.Type targetType) [0x00024] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/SubSystems/Conversion/DefaultConversionManager.cs:106
at Castle.MicroKernel.SubSystems.Conversion.GenericDictionaryConverter+DictionaryHelper`2[TKey,TValue].ConvertConfigurationToCollection (Castle.Core.Configuration.IConfiguration configuration) [0x001bc] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/SubSystems/Conversion/GenericDictionaryConverter.cs:138
at Castle.MicroKernel.SubSystems.Conversion.GenericDictionaryConverter.PerformConversion (Castle.Core.Configuration.IConfiguration configuration, System.Type targetType) [0x000d0] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/SubSystems/Conversion/GenericDictionaryConverter.cs:75
at Castle.MicroKernel.SubSystems.Conversion.DefaultConversionManager.PerformConversion (Castle.Core.Configuration.IConfiguration configuration, System.Type targetType) [0x00025] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/SubSystems/Conversion/DefaultConversionManager.cs:122
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromParameter (Castle.MicroKernel.Context.CreationContext context, Castle.Core.ComponentModel model, Castle.Core.DependencyModel dependency) [0x00058] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Resolvers/DefaultDependencyResolver.cs:411
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromKernel (Castle.MicroKernel.Context.CreationContext context, Castle.Core.ComponentModel model, Castle.Core.DependencyModel dependency) [0x00029] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Resolvers/DefaultDependencyResolver.cs:202
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.TryResolveCore (Castle.MicroKernel.Context.CreationContext context, Castle.MicroKernel.ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, Castle.Core.DependencyModel dependency, System.Object& value) [0x000f8] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Resolvers/DefaultDependencyResolver.cs:342
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.Resolve (Castle.MicroKernel.Context.CreationContext context, Castle.MicroKernel.ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, Castle.Core.DependencyModel dependency) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Resolvers/DefaultDependencyResolver.cs:136
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateConstructorArguments (Castle.Core.ConstructorCandidate constructor, Castle.MicroKernel.Context.CreationContext context) [0x000aa] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs:301
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate (Castle.MicroKernel.Context.CreationContext context) [0x00009] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs:82
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate (Castle.MicroKernel.Context.CreationContext context) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs:63
at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create (Castle.MicroKernel.Context.CreationContext context, Castle.MicroKernel.Burden burden) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/ComponentActivator/AbstractComponentActivator.cs:73
at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance (Castle.MicroKernel.Context.CreationContext context, System.Boolean trackedExternally) [0x0000f] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Lifestyle/AbstractLifestyleManager.cs:79
at Castle.MicroKernel.Lifestyle.SingletonLifestyleManager.Resolve (Castle.MicroKernel.Context.CreationContext context, Castle.MicroKernel.IReleasePolicy releasePolicy) [0x0004a] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Lifestyle/SingletonLifestyleManager.cs:57
at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore (Castle.MicroKernel.Context.CreationContext context, System.Boolean requiresDecommission, System.Boolean instanceRequired, Castle.MicroKernel.Burden& burden) [0x000e4] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Handlers/DefaultHandler.cs:152
at Castle.MicroKernel.Handlers.DefaultHandler.Resolve (Castle.MicroKernel.Context.CreationContext context, System.Boolean instanceRequired) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Handlers/DefaultHandler.cs:97
at Castle.MicroKernel.Handlers.AbstractHandler.Resolve (Castle.MicroKernel.Context.CreationContext context) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/Handlers/AbstractHandler.cs:181
at Castle.MicroKernel.DefaultKernel.ResolveComponent (Castle.MicroKernel.IHandler handler, System.Type service, Castle.MicroKernel.Arguments additionalArguments, Castle.MicroKernel.IReleasePolicy policy, System.Boolean ignoreParentContext) [0x00031] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/DefaultKernel.cs:751
at Castle.MicroKernel.DefaultKernel.ResolveComponent (Castle.MicroKernel.IHandler handler, System.Type service, Castle.MicroKernel.Arguments additionalArguments, Castle.MicroKernel.IReleasePolicy policy) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/DefaultKernel.cs:739
at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve (System.String key, System.Type service, Castle.MicroKernel.Arguments arguments, Castle.MicroKernel.IReleasePolicy policy) [0x00027] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/DefaultKernel_Resolve.cs:175
at Castle.MicroKernel.DefaultKernel.Resolve (System.String key, System.Type service, Castle.MicroKernel.Arguments arguments) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/MicroKernel/DefaultKernel_Resolve.cs:45
at Castle.Windsor.WindsorContainer.Resolve[T] (System.String key) [0x00001] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor/Windsor/WindsorContainer.cs:606
at Castle.MicroKernel.Tests.Configuration.ConfigurationTestCase.DictionaryWithReferencedList () [0x00038] in /Users/nimrodo/dev/repos/Windsor/src/Castle.Windsor.Tests/Config/ConfigurationTestCase.cs:89
at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in /Users/builder/jenkins/workspace/build-package-osx-mono/2020-02/external/bockbuild/builds/mono-x64/mcs/class/corlib/System.Reflection/RuntimeMethodInfo.cs:395

@ni-mi
Copy link
Contributor Author

ni-mi commented Nov 30, 2020

@jonorossi I'd be happy if you could point out what you mean by parameter syntax parsing code.
Do you mean ReferenceExpressionUtil ?
I modified the code a little to use more of the existing code, please review if that is what you meant.
With regards to referenced property - I added a test of dictionary with properties for values - it works.

Another thing - if this fix gets in - when can I expect a new version I can use with this fix?

ni-mi added a commit to ni-mi/Windsor that referenced this issue Dec 4, 2020
ni-mi added a commit to ni-mi/Windsor that referenced this issue Dec 4, 2020
@jonorossi jonorossi added this to the vNext milestone Dec 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants