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

"Sequence contains no matching element" while trying to load recursively assembly that has c++ dependencies #218

Merged
merged 6 commits into from
Jul 12, 2023

Conversation

ivsavchenko
Copy link
Contributor

I get "Sequence contains no matching element" exception while trying to load recursively assembly that has c++ project dependencies.

The problem reside in TypeFactory class line 180 or so. typeDefinition.CustomAttributes.Any(att => att.AttributeType.FullName == typeof(UnsafeValueTypeAttribute).FullName) returns two attributes - UnsafeValueTypeAttribute and NativeCppClassAttribute typeDefinition FullName looks like .$ArrayType$$$BY0GC@$$CB_W

typeDefinition.Fields has no fields so trying to get them leads to an exception here: var arrayType = typeDefinition.Fields.First(field => field.Name == "FixedElementField").FieldType;

Stack trace looks like that:
System.InvalidOperationException
Sequence contains no matching element
at System.Linq.ThrowHelper.ThrowNoMatchException() at System.Linq.Enumerable.First[TSource](IEnumerable1 source, Func2 predicate) at ArchUnitNET.Loader.TypeFactory.CreateTypeFromTypeReference(TypeReference typeReference, Boolean isStub) in \ArchUnitNET\Loader\TypeFactory.cs:line 188 at ArchUnitNET.Loader.TypeFactory.<>c__DisplayClass7_0.b__0(String s) in \ArchUnitNET\Loader\TypeFactory.cs:line 51 at ArchUnitNET.Loader.RegistryUtils.GetFromDictOrCreateAndAdd[T,TK](TK key, Dictionary2 dict, Func2 createFunc) in \ArchUnitNET\Loader\RegistryUtils.cs:line 21 at ArchUnitNET.Loader.TypeRegistry.GetOrCreateTypeFromTypeReference(TypeReference typeReference, Func2 createFunc) in \ArchUnitNET\Loader\TypeRegistry.cs:line 24 at ArchUnitNET.Loader.TypeFactory.GetOrCreateTypeFromTypeReference(TypeReference typeReference) in \ArchUnitNET\Loader\TypeFactory.cs:line 50 at ArchUnitNET.Loader.ArchBuilder.<>c__DisplayClass15_0.b__3(TypeDefinition typeDefinition) in \ArchUnitNET\Loader\ArchBuilder.cs:line 84 at ArchUnitNET.Domain.Extensions.EnumerableExtensions.ForEach[T](IEnumerable1 source, Action1[] actions) in \ArchUnitNET\Domain\Extensions\EnumerableExtensions.cs:line 21 at ArchUnitNET.Loader.ArchBuilder.LoadTypesForModule(ModuleDefinition module, String namespaceFilter) in \ArchUnitNET\Loader\ArchBuilder.cs:line 79 at ArchUnitNET.Loader.ArchLoader.LoadModule(String fileName, String nameSpace, Boolean includeDependencies, Boolean recursive, FilterFunc filterFunc) in \ArchUnitNET\Loader\ArchLoader.cs:line 144 at ArchUnitNET.Loader.ArchLoader.LoadAssembliesRecursively(IEnumerable1 assemblies, FilterFunc filterFunc) in \ArchUnitNET\Loader\ArchLoader.cs:line 205 at Architecture.Tests.ArchUnitExtensions.LoadAssemblyRecursively(ArchLoader loader, String assemblyName)

…to load recursively assembly that has c++ project dependencies.

The problem reside in TypeFactory class line 180 or so.
typeDefinition.CustomAttributes.Any(att => att.AttributeType.FullName == typeof(UnsafeValueTypeAttribute).FullName)
returns two attributes - UnsafeValueTypeAttribute and NativeCppClassAttribute
typeDefinition FullName looks like .$ArrayType$$$BY0GC@$$CB_W

typeDefinition.Fields has no fields so trying to get them leads to an exception here:
var arrayType = typeDefinition.Fields.First(field => field.Name == "FixedElementField").FieldType;

Stack trace looks like that:
System.InvalidOperationException
Sequence contains no matching element
at System.Linq.ThrowHelper.ThrowNoMatchException()
at System.Linq.Enumerable.First[TSource](IEnumerable1 source, Func2 predicate)
at ArchUnitNET.Loader.TypeFactory.CreateTypeFromTypeReference(TypeReference typeReference, Boolean isStub) in \ArchUnitNET\Loader\TypeFactory.cs:line 188
at ArchUnitNET.Loader.TypeFactory.<>c__DisplayClass7_0.b__0(String s) in \ArchUnitNET\Loader\TypeFactory.cs:line 51
at ArchUnitNET.Loader.RegistryUtils.GetFromDictOrCreateAndAdd[T,TK](TK key, Dictionary2 dict, Func2 createFunc) in \ArchUnitNET\Loader\RegistryUtils.cs:line 21
at ArchUnitNET.Loader.TypeRegistry.GetOrCreateTypeFromTypeReference(TypeReference typeReference, Func2 createFunc) in \\ArchUnitNET\Loader\TypeRegistry.cs:line 24 at ArchUnitNET.Loader.TypeFactory.GetOrCreateTypeFromTypeReference(TypeReference typeReference) in \\ArchUnitNET\Loader\TypeFactory.cs:line 50 at ArchUnitNET.Loader.ArchBuilder.<>c__DisplayClass15_0.<LoadTypesForModule>b__3(TypeDefinition typeDefinition) in \\ArchUnitNET\Loader\ArchBuilder.cs:line 84 at ArchUnitNET.Domain.Extensions.EnumerableExtensions.ForEach[T](IEnumerable1 source, Action1[] actions) in \\ArchUnitNET\Domain\Extensions\EnumerableExtensions.cs:line 21 at ArchUnitNET.Loader.ArchBuilder.LoadTypesForModule(ModuleDefinition module, String namespaceFilter) in \\ArchUnitNET\Loader\ArchBuilder.cs:line 79 at ArchUnitNET.Loader.ArchLoader.LoadModule(String fileName, String nameSpace, Boolean includeDependencies, Boolean recursive, FilterFunc filterFunc) in \\ArchUnitNET\Loader\ArchLoader.cs:line 144 at ArchUnitNET.Loader.ArchLoader.LoadAssembliesRecursively(IEnumerable1 assemblies, FilterFunc filterFunc) in \ArchUnitNET\Loader\ArchLoader.cs:line 205
at Architecture.Tests.ArchUnitExtensions.LoadAssemblyRecursively(ArchLoader loader, String assemblyName)

Signed-off-by: Igor Savchenko <[email protected]>
Signed-off-by: isavchenko <[email protected]>
Signed-off-by: Igor Savchenko <[email protected]>
@ivsavchenko ivsavchenko force-pushed the bugfix/check-field-existence branch from 822bc65 to 687ebeb Compare July 10, 2023 20:37
@ivsavchenko ivsavchenko changed the title Pull request related to issue #216 "Sequence contains no matching element" while trying to load recursively assembly that has c++ reference Jul 10, 2023
@ivsavchenko ivsavchenko changed the title "Sequence contains no matching element" while trying to load recursively assembly that has c++ reference "Sequence contains no matching element" while trying to load recursively assembly that has c++ dependencies Jul 10, 2023
@fgather
Copy link
Contributor

fgather commented Jul 11, 2023

Hi @ivsavchenko !
Thanks for the PR ! It looks good to me. Could you also add a test reproducing the issue to prevent regressions?

@ivsavchenko
Copy link
Contributor Author

Hi @fgather !
Thanks for a quick response. I've added test that validates the case. The only problem is that configured Travis can't build c++/cli projects and build with such project failed with error "MSB4019: The imported project "/Microsoft.Cpp.Default.props" was not found".
So in the latest version I've just added prebuilt dll that contains managed c++ code (add added cpp code itself as a comment) into tests so no built action require. Is that suitable for you?

@fgather fgather merged commit ebe55e5 into TNG:main Jul 12, 2023
@fgather
Copy link
Contributor

fgather commented Jul 12, 2023

Hi @ivsavchenko ,

thanks for adding the test. The binary is not really beautiful, but let's be pragmatic :)

Best,
Florian

@ivsavchenko
Copy link
Contributor Author

@fgather I completely agree with you about the binary in tests, I've tried few approaches to keep c++ in separate project in solution instead of binary, but all in all only Travis changes would help, so... yeah. Thanks for the approved PR!

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 this pull request may close these issues.

2 participants