C# `Assembly.GetType(name)`何时返回`null`?

C# `Assembly.GetType(name)`何时返回`null`?,c#,.net,reflection,.net-assembly,C#,.net,Reflection,.net Assembly,我有一个如下所示的代码 public static Type ToType(Type sType) { Assembly assembly = Assembly.Load(SerializableType.AssemblyName); type = assembly.GetType(sType.Name); } 更新 在UI中,如果我为基类设置值没有问题,因为它们的程序集以正常的方式创建,但是如果您为用户定义的类设置值,它们的程序集以不同的方式创建,如下图所示,如果找不

我有一个如下所示的代码

public static Type ToType(Type sType)
{    
    Assembly assembly = Assembly.Load(SerializableType.AssemblyName);
    type = assembly.GetType(sType.Name);
}
更新


在UI中,如果我为基类设置值没有问题,因为它们的程序集以正常的方式创建,但是如果您为用户定义的类设置值,它们的程序集以不同的方式创建,如下图所示,如果找不到类名,则返回
null
,很可能是因为您类型的
name
属性只返回类型名,而不是名称空间名称来限定它。确保
Name
属性也包含限定它的命名空间

public static Type ToType(Type sType)
{    
    Assembly assembly = Assembly.Load(SerializableType.AssemblyName);
    type = assembly.GetType(sType.Name);
}
根据Assembly.GetType(字符串名称)上的MSDN,它返回:

表示指定类的对象,如果该类 找不到

因此,由于您得到的是
null
,它找不到类型名,最可能的原因是它拼写错误,或者您没有在类型名前面加上名称空间

此方法仅搜索当前程序集实例。名字 参数包括命名空间,但不包括程序集

或者,也可能是类型名称的大小写错误,有一个版本的
GetType()
也支持
bool
参数进行不区分大小写的名称比较

p、 因为程序集名称可能不是名称空间的指示符,所以需要名称空间。也就是说,如果我在程序集
MySystem.MyClasses.DLL
中有一个类型,这并不意味着该类型必须在
MySystem.MyClasses
命名空间中

完整的MSDN页面(总是可以看到哪些东西被抛出/返回)如下所示:


很明显程序集存在(或者它将返回
null
,并且您将得到
null引用异常
),因此另一种可能是您没有期望的相同版本的程序集(即,使用此代码的程序与生成数据的代码具有不同版本的程序集).

您的类型可能是非公共的,默认情况下反射只对公共类型和成员有效,除非您提高安全级别,否则类型将为空。

我猜您忘记提到名称空间了。正确的方法是

assembly.GetType(MyNameSpace+sType.Name)

我努力在试图使用的dll中找到类型的正确限定名,但发现GetTypes()在列出所有可用类型时非常有用。在VB中:

    Dim t As Type() = assem.GetTypes()
    Dim s As String = ""
    For i As Integer = 0 To t.Length - 1
        s = s & t(i).FullName & vbCrLf
    Next i
    MsgBox(s)

下面是一个UWP应用程序的实际示例。 应用程序名称空间是My_应用程序。类FooPage位于文件夹视图下。获取类型的方法如下所示:

Type typePage = Assembly.GetExecutingAssembly().GetType("My_App.Views.FooPage}");
如果不确定类型的名称,请使用以下代码转储所有类并查找感兴趣的类:

foreach(Type t in Assembly.GetExecutingAssembly().GetTypes())
{
    Debug.WriteLine($"{t.Namespace}.{t.Name}");
}

这不起作用,因为您从基类程序集以外的其他程序集加载代码。尝试从其他程序集调用此代码而不是从包含搜索类型定义的程序集调用此代码将导致类型解析为null

这是合理的,因为您必须提供程序集限定类型名称,即type.AssemblyQualifiedName,而不仅仅是类型全名本身

如果使用代码示例在基类以外的其他程序集中定义了派生类,则定义了基类的程序集中的代码将无法工作

这会奏效的


您可以使用这样的类型解析器(C#7.2)

MSDN:


但是它没有全名属性,你说的是类型。全名???@rickymartin:我更正了我的帖子,我对你的
xmlSerializableType
有一个错误的假设,你能验证你看到的
Name
属性值代表一个完全限定的类型名吗(即类似System.Collections.ArrayList的内容)@rickymartin:这是在什么环境下使用的?这些类型是通过服务返回到另一台机器上的吗?我删除了某些代码,在唯一的问题出现之后,我发布了删除的代码以及背后的原因it@rickymartin:仍然不确定您是如何使用它的。您是否通过web服务和另一台机器上的另一个程序正在尝试重新创建它们?或者这都在同一个程序中?您能提供一些示例数据吗?可能会有帮助。我很确定这是下面的名称空间问题,但希望确保。也许我们还应该问,这是试图解决的问题,我们可能也知道一个更简单的解决方案…我很好奇w为什么要将
类型
转换为
XmlSerializableType
并返回?为什么要这样做?如果我们知道原因,也许我们可以建议一种更简单的方法来执行相同的任务?或者至少知道更多关于它找不到类的原因。在我们的应用程序的Ui中,我们设置了一个值,保存后,如果我们再次加载应用程序,它的returnignull设置为默认值,这是根本原因。加载应用程序时,在完成某些事件后,服务器部件和客户端部件之间有许多进程正在进行,只有我们应该传递请求,但我们很早就传递了请求,这就是原因该类型的程序集是否具有自动递增的版本属性程序集的
FullName
属性包含版本号,如果每次都从VS运行并重新生成,则可能会碰撞版本,序列化类型将无法加载…
GetType()
可以从程序集返回非公共类型,只有在尝试使用它们时才会遇到潜在问题。这之所以有效,是因为您没有从定义程序集以外的其他程序集加载此代码。尝试从其他程序集调用此代码将导致空值。这是合理的,因为您必须提供程序集质量类型名称,即type.AssemblyQualifiedName,而不仅仅是类型名称
public interface ITypeResolver
{
    string GetName(Type type);
    Type GetType(Assembly assembly, string typeName);
}

class TypeResolver : ITypeResolver
{
    public string GetName(Type type) => type.AssemblyQualifiedName;
    public Type GetType(Assembly assembly, string typeName) =>
        assembly.GetType(typeName) ?? Type.GetType(typeName);
}