通过类名获取程序集

问题描述 投票:0回答:5

有什么方法可以获取包含名称为

TestClass
的类的程序集吗? 我只知道类名,所以我无法创建它的实例。还有

Type objectType = assembly.GetType("TestClass");

对我不起作用。

c# reflection
5个回答
38
投票
Assembly asm = typeof(TestClass).Assembly;

只要引用它,就会为您提供程序集。否则,您将必须使用完全限定名称:

Assembly asm = null;
Type type = Type.GetType("TestNamespace.TestClass, ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
if (type != null)
{
    asm = type.Assembly;
}

28
投票

从问题中的

Type objectType
来看,我假设你是实际上在按名称输入类型(而不是程序集)之后;所以假设程序集已加载并且类型名称是唯一的,LINQ可能会有所帮助:

Type objectType = (from asm in AppDomain.CurrentDomain.GetAssemblies()
                   from type in asm.GetTypes()
                   where type.IsClass && type.Name == "TestClass"
                   select type).Single();
object obj = Activator.CreateInstance(objectType);

但是,使用程序集限定名称而不是类型名称可能会更好。


5
投票

Marc的答案确实很好,但由于太慢(我经常使用该方法),我决定采用不同的方法:

    private static Dictionary<string, Type> types;
    private static readonly object GeneralLock = new object();

    public static Type FindType(string typeName)
    {
        if (types == null)
        {
            lock (GeneralLock)
            {
                if (types == null)
                {
                    types = new Dictionary<string, Type>();
                    var appAssemblies = AppDomain.CurrentDomain.GetAssemblies();
                    foreach (var appAssembly in appAssemblies)
                    {
                        foreach (var type in appAssembly.GetTypes())
                            if (!types.ContainsKey(type.Name))
                                types.Add(type.Name, type);
                    }
                }
            }
        }

        return types[typeName];
    }

您可以按照自己想要的方式处理名称冲突,但在这个示例中,我决定忽略后续的名称冲突。


4
投票

实际上在大多数情况下了解类名就足够了。 MSDN 说 - 如果类型位于当前执行的程序集或 Mscorlib.dll 中,则提供由其命名空间限定的类型名称就足够了。

Type neededType = Type.GetType("TestClass"); //or typeof(TestClass) 
Assembly a = neededType.Assembly;

如果您不知道包含类型的程序集(尽管我无法想象为什么)-

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Asssembly result = assemblies.FirstOrDefault(a=>a.GetType("TestClass",false)!=null);

唯一的限制 - 包含 TestClass 的程序集应该在调用此类代码时已经加载。

希望这会有所帮助。 :)


0
投票

最好的方法是仅存储

Type
FullName
Assembly
Name

var typeFullName = myType.FullName; // Namespace.Name ie. "Core.MyObj"
var assemblyName = myType.Assembly.GetName().Name; // ie. "Core"

通常程序集名称和命名空间是相同的,但并非总是如此。

然后你可以这样做:

var typeName = $"{t.FullName}, {t.Assembly.GetName().Name}"; // "Core.MyObj, Core"

甚至编写一个扩展方法:

public static class TypeExtensions
{
    public static string FullNameAndAssembly(this Type type)
    {
        return $"{type.FullName}, {type.Assembly.GetName().Name}";
    }
}

即使更改

Assembly
版本,这也始终有效:

Type myObjType = Type.GetType("Core.MyObj, Core");

我发现如果

Assembly
的版本发生变化,存储
FullName
Assembly
将无法工作。

Assembly.FullName
的示例:

Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

这行不通,你会得到

null

Type.GetType(
    "Core.MyObj, Core, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null"
);
© www.soinside.com 2019 - 2024. All rights reserved.