C# scripts and Reflection

In our deployment process we want to generate custom instrumentation files for New Relic in build step which uses reflection to scan assemblies for Methods we want to trace.

When we load the Assembly we want to trace function on the dependent assemblies are not loaded and we receive the following exception. (The code we are running works in LinqPad)

System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.Assembly.GetTypes()
at Submission#0.GetMethodsToTrace(Assembly assembly)
at Submission#0..ctor(Object[] submissionArray, Object& submissionResult)

Code Snippet

var assembly = Assembly.LoadFrom(Octopus.Parameters["ServiceExecutable"]);

// This line throws the exception
var consumeMethods =  assembly.GetTypes().SelectMany(t => t.GetMethods().Where(m => m.Name.Equals("Consume")).Where(m => !m.DeclaringType.IsGenericType));

The current work around is to use the following, helper function taken from stackoverflow (http://stackoverflow.com/questions/7889228/how-to-prevent-reflectiontypeloadexception-when-calling-assembly-gettypes) this fixes the exception but we are still missing the some transactions we want to trace.

public IEnumerable<Type> GetLoadableTypes(Assembly assembly)
	if (assembly == null) throw new ArgumentNullException(nameof(assembly));
		return assembly.GetTypes();
	catch (ReflectionTypeLoadException e)
		return e.Types.Where(t => t != null);

Is there a recommended way to use reflection in octopus, which can fix this issue?

Hi Brent,

Thank you for getting in touch. It is hard to tell why it works locally, but not on the octopus server. The most likely reason is that certain assemblies are not available on the destination system. You could try writing out more about the reflection exception (message, inner exception messages, etc) in the catch block.

For C# scripts, Octopus uses ScriptCS. You could try running your script using that locally.

If you do identify the assemblies that are missing, you may need to load them using the ScriptCS #r syntax.

You could also try Assembly.ReflectionOnlyLoad which does not load dependencies.

Hope that helps,

Robert W