忽略程序集限定名称中的版本信息传递给Type.GetType()方法

14

当通过Type.GetType()传入的程序集限定名称与实际加载的DLL的版本不同时,是否可以使用Type获取该类型?如果可以,GetType()的行为是什么?

我想从一个程序集中获取一个Type,而不考虑程序集的版本。我有一个函数,该函数将程序集限定名称作为参数:

Type someType = Type.GetType(someName);

someName 值对应于我想要获取的 Type,但它可能与加载在我的应用程序中的指定 Version 不同。


这个问题不够精确...你想从一个程序集中获取一个类型,但又不知道你想从哪个程序集中获取哪个类型?这听起来不太合乎逻辑。 而“程序集限定名称”的整个目的就是为了在名称中定义版本和标记。 请编辑问题以澄清。 - galaktor
4个回答

20

我已经成功地使用了这个:

Type type = Type.GetType(typeName, AssemblyResolver, null);

private static System.Reflection.Assembly AssemblyResolver(System.Reflection.AssemblyName assemblyName)
{
    assemblyName.Version = null;
    return System.Reflection.Assembly.Load(assemblyName);
}

这对我有用。FYI,在.NET 7中,如果字符串中没有完整的程序集名称,将不会调用解析器。请参阅https://learn.microsoft.com/en-us/dotnet/api/system.type.gettype?view=net-7.0#system-type-gettype(system-string-system-func((system-reflection-assemblyname-system-reflection-assembly))-system-func((system-reflection-assembly-system-string-system-boolean-system-type))) - Rob Baily

1

在测试中,我发现即使当前加载的程序集版本与程序集限定名称中的Version字段的值不匹配,GetType()仍将返回正确的类型。


2
我没有强名称的应用程序,这绝对不是事实。 - BrainSlugs83
2
这取决于 .net 版本,例如 4.7.2 vs 5.0。 - Michael Blake
在 .net6.0 中,它只能在请求较低版本时运行,而不能在请求较高版本时运行。 - undefined

0
另一种可能性是:将类型名称缩短为其FullNameAssemblyName。在“序列化”时使用:
public static string GetShortTypeName(this Type type)
{
  return $"{type.FullName}, {type.Assembly.GetName().Name}";
}

或在“反序列化”之前:

public static string ShortenTypeName(string assemblyQualifiedName)
{
  var cPos1 = assemblyQualifiedName.IndexOf(',');
  if (cPos1 < 0 || cPos1 == assemblyQualifiedName.Length - 1)
    return assemblyQualifiedName;

  var cPos2 = assemblyQualifiedName.IndexOf(',', cPos1 + 1);
  if (cPos2 < 0)
    return assemblyQualifiedName;

  return assemblyQualifiedName.Substring(0, cPos2);
}

在这种情况下,@PJC答案中AssemblyResolver中的assemblyName.Version始终为null,因此不再需要自定义解析器。

这适用于 .Net Framework 和 .NET Core/.NET 5+。


0
在后续版本(插入版本号)的框架中,使用GetType()并给它一个带有错误版本号的类型字符串仍然会返回正确的类型,而不是null。
如果你编写了一个可以被先前版本(插入版本号)的应用程序使用的库,你可以给GetType()方法传递一个不包含版本号的字符串。
请记住,询问泛型类型的fullName将返回一个包含泛型类型参数版本的字符串,你需要自己编写类型字符串。你可以使用我的代码来实现这一点,它使用了@Lars的代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace hlwSerial
{
    public static class TypeHelper
    {
        /// <summary>
        /// Gives a shortened assemblyQualifiedName of the type, with only its fullName and the name of its assembly. Does the same for its generic type parameters if it has any.
        /// </summary>
        /// <param name="type">The type of which you'll get the name</param>
        /// <param name="inBrackets">default to false. Put true if the result should be surrounded by brackets in the case of being a generic type parameter.You shouldn't have to set it to true yourself.</param>
        /// <returns></returns>
        public static string GetShortTypeName(this Type type, bool inBrackets = false)
        {
            if (type.IsGenericType) return type.GetShortGenericName(inBrackets);
            if (inBrackets) return $"[{type.FullName}, {type.Assembly.GetName().Name}]";
            return $"{type.FullName}, {type.Assembly.GetName().Name}";
        }

        /// <summary>
        /// Private function that will be called by the GetShortTypeName method if the type tested is generic.
        /// </summary>
        /// <param name="type">The type of which you'll get the name</param>
        /// <param name="inBrackets">default to false. Put true if the result should be surrounded by brackets in the case of being a generic type parameter. You shouldn't have to use this.</param>
        /// <returns></returns>
        private static string GetShortGenericName(this Type type, bool inBrackets = false)
        {
            if (inBrackets)
                return $"[{type.GetGenericTypeDefinition().FullName}[{string.Join(", ", type.GenericTypeArguments.Select(a => a.GetShortTypeName(true)))}], {type.Assembly.GetName().Name}]";
            else
                return $"{type.GetGenericTypeDefinition().FullName}[{string.Join(", ",type.GenericTypeArguments.Select(a=> a.GetShortTypeName(true)))}], {type.Assembly.GetName().Name}";
        }
    }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接