`Assembly.GetType(name)` 什么时候返回 `null`?

发布于 2024-12-15 21:34:37 字数 308 浏览 2 评论 0原文

我有如下所示的代码

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

更新

在 UI 中,如果我为基类设置值,则没有问题,因为它们的程序集创建正常方式,但如果您为用户定义的类设置值,则它们的程序集创建不同的方式,如下所示

I have a code like shown below

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

UPDATE

In UI if I set value for base class no issues because their assembly creating normal way, but if you set value for user defined class their assembly creating different way like shown below

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

眼波传意 2024-12-22 21:34:37

如果未找到类名,它会返回 null,很可能是因为类型的 Name 属性只返回类型名称,而不是限定它的命名空间名称。确保您的 Name 属性也包含限定它的命名空间。

根据MSDN上的Assembly.GetType(string name),它返回:

表示指定类的对象,如果该类则为 Nothing
未找到。

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

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

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

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

完整的 MSDN 页面(总是很高兴看到抛出/返回的内容)在这里: Assembly .GetType Method(String)

很明显该程序集存在(或者它会返回 null 并且您会得到一个 NullReferenceException),因此还有另一种可能性是您没有所需的相同版本的程序集(即使用此代码的程序具有与生成数据的代码不同版本的程序集)。

It returns null if the class name is not found, most likely because the Name property of your type just returns the type name, and not the namespace name to qualify it. Make sure that your Name property includes the namespace qualifying it as well.

According to the MSDN on Assembly.GetType(string name), it returns:

An object that represents the specified class, or Nothing if the class
is not found.

Thus since you're getting null, it couldn't find the type name, most likely reason is it's either misspelled, or you didn't prepend the type name with the namespace.

This method only searches the current assembly instance. The name
parameter includes the namespace but not the assembly.

Or, it's also possible the case is wrong on the type name, there is a version of GetType() that supports a bool argument for a case-insensitive name compare as well.

p.s. The namespace is needed because the assembly name may not be an indicator of the namespace. That is, if I had a type in an assembly MySystem.MyClasses.DLL, this does not mean that the type is necessarily in the MySystem.MyClasses namespace.

The full MSDN page (always good to see what things throw/return) is here: Assembly.GetType Method(String)

It's evident the assembly exists (or it would return null and you'd get a NullReferenceException), so another possibility is you don't have the same version of the assembly you are expecting (i.e. the program using this code has a different version of the assembly then the code generating the data).

小…红帽 2024-12-22 21:34:37

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

Your type may be non public, by default reflection only works on public types and members, unless you increase your level of security, type will be null.

花海 2024-12-22 21:34:37

我努力在我尝试使用的 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)

I struggled to find the correctly qualified name of a type in a dll I was trying to use, but found GetTypes() really useful in listing all available. In 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)
攀登最高峰 2024-12-22 21:34:37

这是 UWP 应用程序的实际示例。
应用程序命名空间是 My_App。 FooPage 类位于 Views 文件夹下。获取类型的方法如下:

Type typePage = Assembly.GetExecutingAssembly().GetType("My_App.Views.FooPage}");

如果您不确定类型的名称,请使用以下代码转储所有类并找到感兴趣的类:

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

Here is an actual example from a UWP app.
The app namespace is My_App. Class FooPage is under folder Views. The way to get the Type is the following:

Type typePage = Assembly.GetExecutingAssembly().GetType("My_App.Views.FooPage}");

If you are not sure about the name of your type, use the following code to dump all classes and find the one of interest:

foreach(Type t in Assembly.GetExecutingAssembly().GetTypes())
{
    Debug.WriteLine($"{t.Namespace}.{t.Name}");
}
黑色毁心梦 2024-12-22 21:34:37

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

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

如果您在其他程序集中定义的派生类而不是带有代码示例的基类,则来自程序集的代码(其中基类是)定义的将不起作用。

这将起作用


public static Type ToType(Type type, ITypeResolver typeResolver)
{    
    Assembly assembly = Assembly.Load(SerializableType.AssemblyName);
    type = typeResolver.GetType(assembly, sType.AssemblyQualifiedName);
}

您可以使用类似的 TypeResolver (C# 7.2)

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);
}

MSDN:

https://learn.microsoft.com/ru-ru/dotnet/api/system.type.gettype?view=netcore-2.1#System_Type_GetType_System_String_

This is not working just because you load code from other assembly than you base class assembly. Trying to call this code from other assembly than contains definiton of searched type will result in type resolved to null.

It is reasonable, because you have to provide an assembly qualified type name, i.e. Type.AssemblyQualifiedName, not just type full name itself

If you derived classes defined elsewere in another assembly than base class with code sample, your code from assembly where base class is defined will not work.

This will work


public static Type ToType(Type type, ITypeResolver typeResolver)
{    
    Assembly assembly = Assembly.Load(SerializableType.AssemblyName);
    type = typeResolver.GetType(assembly, sType.AssemblyQualifiedName);
}

You can use a TypeResolver like that (C# 7.2)

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);
}

MSDN:

https://learn.microsoft.com/ru-ru/dotnet/api/system.type.gettype?view=netcore-2.1#System_Type_GetType_System_String_

饮惑 2024-12-22 21:34:37

我猜你忘了提到命名空间。正确的方法是

assembly.GetType(MyNameSpace+sType.Name)

I guess you forgot to mention namespaces. The correct way would be

assembly.GetType(MyNameSpace+sType.Name)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文