diff --git a/dscom.sln b/dscom.sln
index eb0ed44..8a321b3 100644
--- a/dscom.sln
+++ b/dscom.sln
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dscom.build", "src\dscom.bu
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "assembly4", "src\dscom.demo\assembly4\assembly4.csproj", "{375866D7-1313-408D-AE5A-A77E48711EDB}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "assembly5", "src\dscom.demo\assembly5\assembly5.csproj", "{ACECABE4-AD32-4618-889F-E210D9564C8F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -95,6 +97,14 @@ Global
{375866D7-1313-408D-AE5A-A77E48711EDB}.Release|Any CPU.Build.0 = Release|Any CPU
{375866D7-1313-408D-AE5A-A77E48711EDB}.Release|x86.ActiveCfg = Release|x86
{375866D7-1313-408D-AE5A-A77E48711EDB}.Release|x86.Build.0 = Release|x86
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Debug|x86.ActiveCfg = Debug|x86
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Debug|x86.Build.0 = Debug|x86
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Release|x86.ActiveCfg = Release|x86
+ {ACECABE4-AD32-4618-889F-E210D9564C8F}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -109,6 +119,7 @@ Global
{5B402A1B-18B1-4D88-804A-BC0E58EF3730} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{375866D7-1313-408D-AE5A-A77E48711EDB} = {CAAB6257-7EC0-484E-9593-B60CEE8F47D1}
+ {ACECABE4-AD32-4618-889F-E210D9564C8F} = {CAAB6257-7EC0-484E-9593-B60CEE8F47D1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3F23D9EA-A9D9-4CE5-94B5-050A9B68CA1C}
diff --git a/src/dscom.demo/assembly5/ExplodeyBaseClass.cs b/src/dscom.demo/assembly5/ExplodeyBaseClass.cs
new file mode 100644
index 0000000..1b7e75b
--- /dev/null
+++ b/src/dscom.demo/assembly5/ExplodeyBaseClass.cs
@@ -0,0 +1,7 @@
+using System.Windows.Controls;
+
+namespace dSPACE.Runtime.InteropServices.DemoAssembly5;
+
+public class ExplodeyBaseClass : UserControl
+{
+}
diff --git a/src/dscom.demo/assembly5/ExplodeyMember.cs b/src/dscom.demo/assembly5/ExplodeyMember.cs
new file mode 100644
index 0000000..2d7905f
--- /dev/null
+++ b/src/dscom.demo/assembly5/ExplodeyMember.cs
@@ -0,0 +1,9 @@
+using System.Windows.Controls;
+
+namespace dSPACE.Runtime.InteropServices.DemoAssembly5;
+
+public class ExplodeyMember
+{
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Example")]
+ public UserControl Control => null!;
+}
diff --git a/src/dscom.demo/assembly5/ExplodeyParameter.cs b/src/dscom.demo/assembly5/ExplodeyParameter.cs
new file mode 100644
index 0000000..6deeca5
--- /dev/null
+++ b/src/dscom.demo/assembly5/ExplodeyParameter.cs
@@ -0,0 +1,13 @@
+using System.Windows.Controls;
+
+namespace dSPACE.Runtime.InteropServices.DemoAssembly5;
+
+public class ExplodeyParameter
+{
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "example")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "example")]
+ public void Example(UserControl thing)
+ {
+ // nop
+ }
+}
diff --git a/src/dscom.demo/assembly5/IExportableType.cs b/src/dscom.demo/assembly5/IExportableType.cs
new file mode 100644
index 0000000..cf4ffac
--- /dev/null
+++ b/src/dscom.demo/assembly5/IExportableType.cs
@@ -0,0 +1,9 @@
+using System.Runtime.InteropServices;
+
+namespace dSPACE.Runtime.InteropServices.DemoAssembly5;
+
+[ComVisible(true), Guid("E27C3BDB-ACEF-44F9-8568-481D44681C04"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+public interface IExportableType
+{
+ void DoIt();
+}
diff --git a/src/dscom.demo/assembly5/Properties/AssemblyInfo.cs b/src/dscom.demo/assembly5/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ce565d0
--- /dev/null
+++ b/src/dscom.demo/assembly5/Properties/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using System.Runtime.InteropServices;
+
+[assembly: ComVisible(false)]
diff --git a/src/dscom.demo/assembly5/assembly5.csproj b/src/dscom.demo/assembly5/assembly5.csproj
new file mode 100644
index 0000000..34325f8
--- /dev/null
+++ b/src/dscom.demo/assembly5/assembly5.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net6.0-windows;net48
+ AnyCPU
+ 10.0
+ enable
+ enable
+ dSPACE.Runtime.InteropServices.DemoAssembly5
+ dSPACE.Runtime.InteropServices.DemoAssembly5
+ true
+ Recommended
+ true
+ AnyCPU;x86
+ true
+
+
+ true
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/dscom/AssemblyExtensions.cs b/src/dscom/AssemblyExtensions.cs
index 225f918..dbb9b4b 100644
--- a/src/dscom/AssemblyExtensions.cs
+++ b/src/dscom/AssemblyExtensions.cs
@@ -51,4 +51,24 @@ public static TypeLibIdentifier GetLibIdentifier(this Assembly assembly)
{
return assembly.GetLibIdentifier(Guid.Empty);
}
+
+ internal static IEnumerable GetLoadableTypes(this Assembly assembly)
+ {
+ return GetLoadableTypesAndLog(assembly, null);
+ }
+
+ internal static IEnumerable GetLoadableTypesAndLog(this Assembly assembly, WriterContext? context)
+ {
+ try
+ {
+ return assembly.GetTypes();
+ }
+ // https://stackoverflow.com/questions/7889228/how-to-prevent-reflectiontypeloadexception-when-calling-assembly-gettypes
+ catch (ReflectionTypeLoadException e)
+ {
+ context?.LogWarning($"Type library exporter encountered an error while processing '{assembly.GetName().Name}'. Error: {e.LoaderExceptions.First()!.Message}");
+
+ return e.Types.Where(t => t is not null)!;
+ }
+ }
}
diff --git a/src/dscom/MethodBaseExtensions.cs b/src/dscom/MethodBaseExtensions.cs
new file mode 100644
index 0000000..fb456c1
--- /dev/null
+++ b/src/dscom/MethodBaseExtensions.cs
@@ -0,0 +1,43 @@
+// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors
+//
+// 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.
+
+using System.ComponentModel;
+using System.Reflection;
+
+namespace dSPACE.Runtime.InteropServices;
+
+///
+/// Extension methods for .
+///
+[Browsable(false)]
+internal static class MethodBaseExtensions
+{
+ ///
+ /// Return the parameters defined in a method, or an empty array if the
+ /// parameter types are unloadable
+ ///
+ /// The method to enumerate
+ /// The loadable parameters
+ internal static IEnumerable GetLoadableParameters(this MethodInfo method)
+ {
+ try
+ {
+ return method.GetParameters();
+ }
+ catch
+ {
+ return Array.Empty();
+ }
+ }
+}
diff --git a/src/dscom/TypeExtensions.cs b/src/dscom/TypeExtensions.cs
new file mode 100644
index 0000000..0ace7ba
--- /dev/null
+++ b/src/dscom/TypeExtensions.cs
@@ -0,0 +1,61 @@
+// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors
+//
+// 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.
+
+using System.ComponentModel;
+using System.Reflection;
+
+namespace dSPACE.Runtime.InteropServices;
+
+///
+/// Extension methods for .
+///
+[Browsable(false)]
+internal static class TypeExtensions
+{
+ ///
+ /// Return the members defined in a type, or an empty array if the
+ /// members cannot be enumerated.
+ ///
+ /// The type to enumerate
+ /// The members which were able to be enumerated
+ internal static IEnumerable GetLoadableMembers(this Type type)
+ {
+ try
+ {
+ return type.GetMembers();
+ }
+ catch
+ {
+ return Array.Empty();
+ }
+ }
+
+ ///
+ /// Return the methods defined in a type, or an empty array if the
+ /// methods cannot be enumerated.
+ ///
+ /// The type to enumerate
+ /// The Methods which were able to be enumerated
+ internal static IEnumerable GetLoadableMethods(this Type type)
+ {
+ try
+ {
+ return type.GetMethods();
+ }
+ catch
+ {
+ return Array.Empty();
+ }
+ }
+}
diff --git a/src/dscom/names/ComAliasNameResolver.cs b/src/dscom/names/ComAliasNameResolver.cs
index f033389..d3c379f 100644
--- a/src/dscom/names/ComAliasNameResolver.cs
+++ b/src/dscom/names/ComAliasNameResolver.cs
@@ -24,7 +24,7 @@ internal sealed class ComAliasNameResolver : INameResolver
public ComAliasNameResolver(Assembly assembly)
{
- var comVisibleTypes = assembly.GetTypes().Where(t => t.IsPublic && t.GetCustomAttribute() != null);
+ var comVisibleTypes = assembly.GetLoadableTypes().Where(t => t.IsPublic && t.GetCustomAttribute() != null);
var types = comVisibleTypes
.Where(t => t.GetCustomAttribute() != null)
.ToDictionary(t => t as object, t => t.GetCustomAttribute()?.Alias ?? string.Empty)
@@ -35,7 +35,7 @@ public ComAliasNameResolver(Assembly assembly)
}
var members = comVisibleTypes
- .SelectMany(t => t.GetMembers().Where(m => m.GetCustomAttribute() != null))
+ .SelectMany(t => t.GetLoadableMembers().Where(m => m.GetCustomAttribute() != null))
.ToDictionary(m => m as object, m => m.GetCustomAttribute()?.Alias ?? string.Empty)
;
foreach (var kv in members)
@@ -44,8 +44,8 @@ public ComAliasNameResolver(Assembly assembly)
}
var parameters = comVisibleTypes
- .SelectMany(t => t.GetMethods())
- .SelectMany(m => m.GetParameters().Where(p => p.GetCustomAttribute() != null))
+ .SelectMany(t => t.GetLoadableMethods())
+ .SelectMany(m => m.GetLoadableParameters().Where(p => p.GetCustomAttribute() != null))
.ToDictionary(p => p as object, p => p.GetCustomAttribute()?.Alias ?? string.Empty)
;
foreach (var kv in parameters)
diff --git a/src/dscom/writer/LibraryWriter.cs b/src/dscom/writer/LibraryWriter.cs
index 8eb098c..c097d33 100644
--- a/src/dscom/writer/LibraryWriter.cs
+++ b/src/dscom/writer/LibraryWriter.cs
@@ -91,21 +91,7 @@ private void CollectAllTypes()
var comVisibleAttributeAssembly = Assembly.GetCustomAttribute();
var typesAreVisibleForComByDefault = comVisibleAttributeAssembly == null || comVisibleAttributeAssembly.Value;
- Type?[] types;
- try
- {
- types = Assembly.GetTypes().ToArray();
- }
- catch (ReflectionTypeLoadException e)
- {
- Context.LogWarning($"Type library exporter encountered an error while processing '{Assembly.GetName().Name}'. Error: {e.LoaderExceptions.First()!.Message}");
-
- if (!e.Types.Any(t => t != null))
- {
- throw e.LoaderExceptions.First()!;
- }
- types = e.Types;
- }
+ var types = Assembly.GetLoadableTypesAndLog(Context);
List classInterfaceWriters = new();