I have a net 6 F# binary that contains some methods, on which some have one or many [<TestCategory(CategoryName)>] attribute defined on them. My goal is to use reflection, from a C# application, to read and gather the fully qualified names of those test methods.
In order to achieve this, I am trying to use the Mono.Cecil library in order to read the information from the F# binary. This seems to work pretty well with C# binaries, but not so much with F# ones. The problem I am encountering is that the fully qualified name (and name) properties of the method Mono.Cecil gives me is under the format "BinaryName.ModuleName.f@LineNumber", instead of giving me "BinaryName.ModuleName.ActualMethodName".
Here is how I get the information via reflection using Mono.Cecil.
private static IEnumerable<GenericModule> ReadModulesRecursively(string assemblyPath)
{
var modules = new List<GenericModule>();
var assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyPath);
foreach (var module in assemblyDefinition.Modules)
{
var moduleTypes = module.Types.Select(ToGenericType); // Construct a DTO containing only what I want
modules.Add(new GenericModule(module.Name, moduleTypes));
}
return modules;
}
private static GenericType ToGenericType(TypeDefinition typeDefinition)
{
return new GenericType(typeDefinition.Name, typeDefinition.CustomAttributes.Select(ToGenericAttribute), typeDefinition.Methods.Select(ToGenericMethod));
}
private static GenericMethod ToGenericMethod(MethodDefinition methodDefinition)
{
return new GenericMethod(methodDefinition.Name, $"{methodDefinition.DeclaringType.FullName}.{methodDefinition.Name}", methodDefinition.DeclaringType.FullName,
methodDefinition.CustomAttributes.Select(ToGenericAttribute));
}
And here is an example of a F# method declaration I am trying to get information on, in the F# binary:
module myModule
<open statements...>
[<TestClass>]
[<DeploymentItem("Deploy1")>]
[<DeploymentItem("Deploy2")>]
type Tests ()=
[<TestMethod>]
[<TestCategory("Cat1")>]
[<TestCategory("Cat2")>]
member x.``This is a test title`` () =
()
So the problem here seems to be that the MonoCecil MethodDefinition type doesn't contain the right Name and FullName property values.
Is this a known issue with MonoCecil and F#, or am I doing something wrong?
You haven't given us enough of your code to reproduce what you're seeing, but this short test seems to work correctly (or at least differently from what you're describing):
Note that the method's
Nameproperty is"This is a test title", as expected. TheFullNamealso looks correct, although I can't say for certain.Neither of the outputs follow the pattern you describe, so I suspect the problem is actually in your code. However, without seeing more of your program, it's hard to say for sure.
It's important to understand that the F# compiler's idea of a module doesn't necessarily correspond to what you might expect. In particular, the F#
myModulemodule gets compiled into a type that then contains a nestedTeststype.