Get Assemblies Without Instantiating Them

假如想象 提交于 2019-12-10 17:35:26

问题


I am trying to get all assemblies in CurrentDomain using AppDomain.CurrentDomain.GetAssemblies() to write their FullName into a DropDownList, however if I don't instantiate them, they are not seen in returned array from GetAssemblies() in CurrentDomain.

They are all added as Reference and in Reference folder of the solution. Only time I can get them from the GetAssemblies() is when I first instantiate them.

How to overcome this problem with an easy and more generic way instead of instantiate them everytime when I add new Assembly, etc.

Due to company policy, I have to obfuscate some parts of the images:

All the assembilies are referenced in Reference folder:


回答1:


There is actually something subtle that happens here in addition to the other people's comments.

VisualStudio actually does not add .dll references to the assembly manifest of your built assembly's reflection info unless they are actually used.

As a sample, make a new project, and reference an assembly. I used nunit.framework.dll as an example.

But don't actually use it. My code is simply:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

But the Project does have a reference to NUnit in VisualStudio. Now build it, and open the assembly in ildasm.exe and the top of the manifest is:

// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly ConsoleApplication1
{
    ...etc...

Now, in the code, just use anything from NUnit:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Assert.IsTrue(true);
        }
    }
}

Again rebuild and check the assembly manifest in ildasm.exe:

// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly extern nunit.framework
{
  .publickeytoken = (96 D0 9A 1E B7 F4 4A 77 )                         // ......Jw
  .ver 2:6:0:12051
}
.assembly ConsoleApplication1
{
    ...etc...

Note that now there is an extern in the IL. This also feeds reflection, so it knows what the dependent assemblies are to be loaded.

Past that little detail, as other have stated, the runtime doesn't actually load an assembly until it is needed for the first time, hence your AppDomain doesn't have the assemblies loaded until you instantiate or use something from that assembly.


That detail above comes into play when you start to try to use the Assembly.GetReferencedAssemblies() method.

So in VisualStudio, I have a project that has these references:

Microsoft.CSharp
nunit.framework
System
System.Core
System.Data
System.Xml
System.Xml.Linq

Then I have the C# code:

using System;
using System.Reflection;
using NUnit.Framework;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
            foreach (var assemblyName in assemblies)
            {
                Console.WriteLine(assemblyName.FullName);
            }
            Console.ReadKey();
        }
    }
}

Note that I even have a using NUnit.Framework; statement! But I don't actually use NUnit anywhere, so it is not a referenced assembly. The output of running this is:

mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

That is it. If I add this line into my test app:

Assert.IsTrue(true);

Now something actually uses NUnit,a nd my console output is:

mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
nunit.framework, Version=2.6.0.12051, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77



回答2:


Until you instantiate types or dependent-types they're not loaded. So if your project references a ton of assemblies but doesn't instantiate any of the types within them, your app doesn't incur the perf hit of loading those bits off disk.

If you want to find out what assemblies your project references, you'll have to explore your assembly using .NET Reflection. Specifically, I suggest you take a look at the Assembly.GetReferencedAssemblies() method.

HTH.




回答3:


This is what I did and worked for me:

Private Sub Pre_Load()
    Dim sBasePath As String = AppDomain.CurrentDomain.BaseDirectory
    Dim sAllFiles() As String = Directory.GetFiles(sBasePath)
    For Each sAssemblyFile As String In sAllFiles
        If sAssemblyFile.EndsWith(".dll") Then
            If Not Me.HasThisAssembly(sAssemblyFile) Then
                Assembly.Load(AssemblyName.GetAssemblyName(sAssemblyFile))
            End If
        End If
    Next
End Sub

Private Function HasThisAssembly(ByVal vsAssemblyName As String) As Boolean
    For Each oAssembly As Assembly In AppDomain.CurrentDomain.GetAssemblies()
        Dim oFile As New FileInfo(vsAssemblyName)
        If oFile.Name = oAssembly.GetName().Name + ".dll" Then
            Return True
            Exit Function
        End If
    Next
    Return False
End Function


来源:https://stackoverflow.com/questions/9947882/get-assemblies-without-instantiating-them

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!