获取的System.Type从在运行时加载的组件(Getting the System.Type f

2019-10-20 00:40发布

作为后续到这个问题,我现在已经来到了能够得到的问题Type由他自己的解决方案,用户定义的类型。 使用标准mscorlib类型,一切正常。

现在的问题是很容易的:我怎样才能得到这个类型从一个程序集,我只知道在运行时?

作为描述这里的评论 :

另外,你是什么意思“抽取式”是什么意思? 你的意思是让反射式? 有没有好帮手,一方面是因为(通常情况下)你不能假设你对编译类型是在运行时可创建。 有间“编译时间”和“运行时间”一强(往往被忽视)的区别,这是罕见的填补他们。

还是在这里前面的问题:

好了,就得到一个TypeTypeInfo ,除了命名问题,是一个棘手的问题。 它假定您有可以加载和发现的组件。 当你做一个构建,编译器可能会加载一个自己无法加载“正常”组件引用程序集。 即使是这样,你可能要挂钩AppDomain.AssemblyResolve找到你的推荐,你建的任何组件。

“构建”和“运行”真的是不同的领域,从一个到另一个路口被定义不清,充其量。 我这里假设你真的需要一个System.Type的,因为你使用的是其他反射API,或者试图然后加载类型,并从它执行代码。

我跟了作为中规定的方法在这里和我的分析仪中实现它是这样:

private static Dictionary<string, Assembly> _assemblies = new Dictionary<string, Assembly>();

var containingAssembly = semanticModel.GetSymbolInfo(argument)
                                      .Symbol
                                      .ContainingAssembly;

if (!_assemblies.TryGetValue(containingAssembly.ToString(), out Assembly result))
{
    var newAssembly = Assembly.Load(containingAssembly.ToString());
    _assemblies.Add(containingAssembly.ToString(), newAssembly);
}

var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += ResolveAssemblies;

private Assembly ResolveAssemblies(object sender, ResolveEventArgs args)
{
    _assemblies.TryGetValue(args.Name, out Assembly result);
    return result;
}

但是,这还没有做出区别,我不断收到

用户诊断分析器“DiagnosticTools.Collections.ElementaryMethodsNotOverriden.ElementaryMethodsNotOverridenAnalyzer”引发了异常与消息“无法加载文件或程序集‘RoslynTester,版本= 1.0.0.0,文化=中性公钥=空’或它的一个依赖。 该系统找不到指定的文件。'。

使用fuslogvw.exe给我这个日志信息这归结为

日志:所有探测网址企图失败了。

搜索后.dll.exe中的几个子文件夹版本/Common7/IDE/

作为上下文解释,为什么我这样做:我要检查每一个是用于收集并验证它会覆盖类型EqualsGetHashCode 。 为了确定这一点,我有一个检查这对我来说是“经典”的反思扩展方法:

public static bool IsOverridden(this MethodInfo method)
{
    return method.GetBaseDefinition().DeclaringType != method.DeclaringType;
}

所以应该罗斯林有一种方法来验证这一点本身,将让这个我没有在所有使用的经典反射,那么这也将是罚款。

更新:

当我使用此代码,通过MSDN提供的 ,我得在Visual Studio中的“无效的参数”异常,但fuslogvw仍显示“未找到文件”的错误消息。 是什么原因导致这种差异?

private Assembly ResolveAssemblies(object sender, ResolveEventArgs args)
{
    Assembly MyAssembly, objExecutingAssemblies;
    string strTempAssmbPath = "";

    objExecutingAssemblies = Assembly.GetExecutingAssembly();
    AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();

    foreach (AssemblyName strAssmbName in arrReferencedAssmbNames)
    {
        if (strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(",")) == args.Name.Substring(0, args.Name.IndexOf(",")))
        {               
            strTempAssmbPath = @"C:\Users\Jeroen\Documents\Visual Studio 2013\Projects\RoslynTester\RoslynTester\bin\Debug\" + args.Name.Substring(0, args.Name.IndexOf(",")) + ".exe";
            break;
        }
    }                   
    MyAssembly = Assembly.LoadFrom(strTempAssmbPath);

    return MyAssembly;
}

Answer 1:

我假设你已经发现了(编程)的类都包含您的收藏。 你并不真正需要的反射来完成你想要的。 随着罗斯林您可以检查如果一个类覆盖Equals方法与此SyntaxWalker

public class FindOverrides : CSharpSyntaxWalker
{
    public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        base.VisitMethodDeclaration(node);

        if (node.Identifier.Text == "Equals" 
            && node.Modifiers.Any(m => m.Text == "override"))
        {
            // found an override of Equals()    
        }
    }
}

到(盲目地)检查每个类型的每个方法在给定的溶液中也可以这样使用:

var syntaxRoots =
    from project in solution.Projects
    from document in project.Documents
    select document.GetSyntaxRootAsync().Result;

foreach (var root in syntaxRoots)
    new FindOverrides().Visit(root);

至少有一个遗漏(如果这是一个有效的情况下你):我上面的代码不会发现,如果一个基类的给定类型的被覆盖Equals()



文章来源: Getting the System.Type from an assembly loaded at runtime