There are a few problems with your code:
- Your combination of
Seq.fold
,Seq.append
andSeq.empty
is a poor implementation ofSeq.collect
oryield!
in sequence expression. - You don't need options here, just skip generation in sequence expression or use Seq.choose.
- You don't need
Array.toSeq
orList.toSeq
when you apply functions on sequences to lists/arrays.try ... with | :? System.Exception
can be shortened totry ... with _
Your expandDir
function isn't tail-recursive. If you change it to use sequence expression, it is optimized using CPS so StackOverflow doesn't happen.
Here is an improved version. I think it is more readable and probably faster.
let ListMethodsInAssembly (input : AssemblyName) =
try
let appd = AppDomain.CreateDomain("temp")
try
let assm = Assembly.Load(input)
assm.GetTypes()
|> Seq.collect (fun ty -> ty.GetMethods())
|> Seq.filter (fun x -> x.Name <> "GetType" && x.Name <> "ToString" && x.Name <> "GetHashCode" && x.Name <> "GetType")
finally
AppDomain.Unload(appd)
with _ -> Seq.empty
let ListAllDlls =
let rec expandDir (parent : DirectoryInfo) =
let getAssemblyNameFromFile (f : FileInfo) =
try
[ AssemblyName.GetAssemblyName f.FullName ]
with _ -> []
seq {
for f in parent.GetFiles() do
yield! getAssemblyNameFromFile f
for subDir in parent.GetDirectories() do
yield! expandDir subDir
}
let basePath = "c:\\Windows\\Microsoft.NET\\assembly\\"
let loc = ["GAC_64"; "GAC_MSIL";]
seq {
for l in loc do
let path = basePath + l
yield! expandDir (DirectoryInfo(path))
}
[<EntryPoint>]
let main args =
ListAllDlls
|> Seq.collect ListMethodsInAssembly
|> Seq.iter (fun x -> printfn "%s" x.Name)
0