为什么反射搜索会突然找不到任何东西?

发布于 2025-01-02 02:57:00 字数 862 浏览 3 评论 0原文

我根据这个问题和答案有以下代码 如何获取 ASP.NET C# 中请求的文件的 MIME 类型? 它工作得非常好:

    static MimeMappingWrapper()
    {
        // dirty trick - Assembly.LoadWIthPartialName has been deprecated        
        //Assembly ass = Assembly.LoadWithPartialName("System.Web");
        Assembly ass = Assembly.GetAssembly(typeof (HttpApplication));
        Type mimeMappingType = ass.GetType("System.Web.MimeMapping");

        GetMimeMappingMethod = mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic);
    }

现在突然 mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic) 返回 null

可能是什么原因?应用程序中没有任何特殊的更改,即使更改了,它如何影响包装类的构造函数?

I had the following code as per this question&answer How do I get the MIME type of a file being requested in ASP.NET C#?
and it was working perfectly fine:

    static MimeMappingWrapper()
    {
        // dirty trick - Assembly.LoadWIthPartialName has been deprecated        
        //Assembly ass = Assembly.LoadWithPartialName("System.Web");
        Assembly ass = Assembly.GetAssembly(typeof (HttpApplication));
        Type mimeMappingType = ass.GetType("System.Web.MimeMapping");

        GetMimeMappingMethod = mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic);
    }

Now suddenly the mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic) returns null.

What could be the reason? Nothing special was changed in the application and even if it was, how could it influence this constructor for the wrapper class?

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

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

发布评论

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

评论(2

坦然微笑 2025-01-09 02:57:00

我的猜测是服务器上安装的 .NET Framework 已升级,并且私有构造函数在新版本下不再存在。

程序集开发人员(在本例中为 Microsoft)可以随心所欲地更改任何私有(或内部)类型或成员,而不会被视为重大更改。

编辑:我在.NET 4.0下检查了我的电脑,该方法仍然存在。这是它的签名:

// System.Web.MimeMapping
internal static string GetMimeMapping(string FileName)

此时,我的两个建议是在运行时检查您的实际 .NET 版本……

var version = System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion();

并枚举 MimeMapping 类的方法来检查它们是否符合您的期望:

var methods = mimeMappingType.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);

更新:好消息是MimeMapping 类及其 GetMimeMapping 方法看起来可能会在 .NET 4.5 中公开。

但是,这意味着您的代码肯定会崩溃,因为您只搜索 NonPublic 方法。尝试执行全包搜索并查看 GetMimeMapping 是否显示:

var methods = mimeMappingType.GetMethods(
    BindingFlags.Instance | 
    BindingFlags.Static | 
    BindingFlags.Public |
    BindingFlags.NonPublic | 
    BindingFlags.FlattenHierarchy);

My guess would be that the .NET Framework installed on the server got upgraded, and the private constructor is no longer present under the new version.

Assembly developers (in this case, Microsoft) are allowed to change any private (or internal) types or members at their whim, without it being considered to have been a breaking change.

Edit: I checked on my PC under .NET 4.0, and the method is still present. This is its signature:

// System.Web.MimeMapping
internal static string GetMimeMapping(string FileName)

At this point, my two suggestions would be to check your actual .NET version at runtime…

var version = System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion();

…and to enumerate the methods of the MimeMapping class to check whether they correspond to what you expect:

var methods = mimeMappingType.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);

Update: The good news is that the MimeMapping class and its GetMimeMapping method seem like they might be made public in .NET 4.5.

However, this means that your code would definitely break, since you’re only searching for NonPublic methods. Try performing an all-inclusive search instead and see whether GetMimeMapping shows up:

var methods = mimeMappingType.GetMethods(
    BindingFlags.Instance | 
    BindingFlags.Static | 
    BindingFlags.Public |
    BindingFlags.NonPublic | 
    BindingFlags.FlattenHierarchy);
木緿 2025-01-09 02:57:00

我自己刚刚遇到了这个问题,可以提供一些额外的背景信息:

Microsoft 对 dll 进行了半升级(例如将 MimeMapping 从“内部”更改为“公共”)。计划将这些更改完全纳入框架的下一版本。

在 .NET 4.0 及以上版本中,为了防止开发人员在较新的系统上使用这些修改(他们可能不知道它会在未打补丁的计算机上崩溃),IDE 在“参考程序集”文件夹中使用代码签名的快照(而不是运行时的程序集)来自 GAC),在主要版本之间不会发生变化。

这意味着尽管运行时类型是公共的,但您的 IDE 只能看到内部版本,因​​此您仍然无法在没有反射的情况下使用它。

您的代码只需更改以检查 Public 和 NonPublic 绑定标志,以满足正在使用的版本。在该框架的下一个版本中,您可能只能使用该类型而无需反射。

Just ran into this myself, and can give a little extra context:

Microsoft do demi-upgrades to dlls (such as changing MimeMapping from "internal" to "public"). The plan is that those changes go fully into the next version of the framework.

In .NET 4.0 onwards, to prevent developers from using these modifications on newer systems (who might not know it would break on unpatched computers), the IDE uses a snapshot of the code signatures in a "Reference Assemblies" folder (not the runtime ones from the GAC), which do not change between major versions.

This means that despite the runtime type being public, your IDE can only see the internal version, therefore you still cannot use it without reflection.

Your code needs to only change to check with both Public and NonPublic binding flags to cater for which ever version happens to be in use. In the next version of the framework, you will probably just be able to use the type without reflection.

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