【问题标题】:Type.GetType not finding a type by nameType.GetType 未按名称查找类型
【发布时间】:2012-07-02 00:58:04
【问题描述】:

我正在尝试使用 StructureMap 执行运行时类型注册,但在使用 Type.GetType() 在引用的程序集中定位类型时遇到问题。这是我的测试应用程序的完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using StructureMap;
using StructureMap.Configuration.DSL;
using StructureMap.Graph;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            ObjectFactory.Initialize(r => r.Scan(
                s => {
                    s.AssembliesFromPath(
                        @"c:\Path\To\MyClasses\bin\Debug");
                    s.Convention<MyConvention>();
                }
                                              ));

            ObjectFactory.AssertConfigurationIsValid();

            foreach (var name in MyConvention.assemblyQualifiedTypenames) {
                Console.WriteLine(name);
                Console.WriteLine("Type found for reflection by assembly qualified name: {0}", Type.ReflectionOnlyGetType(name, false, false) != null);
                Console.WriteLine("Type found by assembly qualified name: {0}", Type.GetType(name) != null);
                Console.WriteLine("Type found by search: {0}",
                    AppDomain.CurrentDomain.GetAssemblies().ToList()
                    .SelectMany(assembly => assembly.GetTypes().Where(t => t.AssemblyQualifiedName == name))
                    .FirstOrDefault() != null
                );
            }
            Type type = null;
            foreach (var name in MyConvention.fullnames) {
                Console.WriteLine(name);
                Console.WriteLine("Type found by full name: {0}", Type.GetType(name) != null);
                Console.WriteLine("Type found by search: {0}",
                    AppDomain.CurrentDomain.GetAssemblies().ToList()
                    .SelectMany(assembly => assembly.GetTypes().Where(t => t.FullName == name))
                    .FirstOrDefault() != null
                );
            }
            foreach (var name in MyConvention.typenames) {
                Console.WriteLine(name);
                Console.WriteLine("Type found by name: {0}", Type.GetType(name) != null);
                Console.WriteLine("Type found by search: {0}",
                    (type = AppDomain.CurrentDomain.GetAssemblies().ToList()
                    .SelectMany(assembly => assembly.GetTypes().Where(t => t.Name == name))
                    .FirstOrDefault()) != null
                );
            }
            Console.ReadLine();
            var instance = ObjectFactory.GetInstance(type);
            Console.WriteLine("Type instance retrieved from StructureMap: {0}", instance != null);
            Console.ReadLine();
            ObjectFactory.WhatDoIHave()
                .Split(new [] { Environment.NewLine}, StringSplitOptions.None)
                .Where(s => s.Contains("Class2")).ToList()
                .ForEach(Console.WriteLine);
            Console.ReadLine();
        }

        private class MyConvention : IRegistrationConvention {
            public static List<string> typenames = new List<string>();
            public static List<string> fullnames = new List<string>(); 
            public static List<string> assemblyQualifiedTypenames = new List<string>(); 
            public void Process(Type type, Registry registry) {
                if (type.GetCustomAttributes(false).Any(o => o.GetType().Name == "MyClassAttribute")) {
                    registry.For(type).Use(type);
                    typenames.Add(type.Name);
                    fullnames.Add(type.FullName);
                    assemblyQualifiedTypenames.Add(type.AssemblyQualifiedName);
                }
            }
        }
    }
}

测试类定义:

namespace MyAttributes {
    public class MyClassAttribute : Attribute { }
}

namespace MyClasses {
    public class MyClass1 { }

    [MyClass]
    public class MyClass2 { }
}

运行控制台应用程序的输出:

MyClasses.Class2,MyClasses,版本=1.0.0.0,文化=中性,PublicKeyToken=null 通过程序集限定名称找到用于反射的类型:False 按程序集限定名称找到的类型:False 通过搜索找到的类型:True MyClasses.Class2 按全名找到的类型:False 通过搜索找到的类型:True 2 类 按名称找到的类型:False 通过搜索找到的类型:True 从 StructureMap 检索的类型实例:True Class2 (MyClasses.Class2) 60eb30ad-ae50-413d-884f-04743ea3148c MyClasses.Class2、MyClasses、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null 的已配置实例 60eb30ad-ae50-413d-884f-04743ea3148c MyClasses.Class2、MyClasses、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null 的已配置实例

我已经完成了基于 this SO post 的所有测试 - 我是否遗漏了一些基本的东西?

【问题讨论】:

    标签: c# reflection structuremap


    【解决方案1】:

    问题是您尝试使用Type.GetType(name) 获取类型。因此.net 将尝试定位程序集本身 - 在 GAC 中或与正在执行的程序集相同的目录中。由于它位于不同的目录中,因此无法找到它。您可以通过将包含 MyClasses 的可执行文件复制到与控制台应用程序相同的目录中来确认这一点 - 然后它就可以工作了。

    出于类似原因,它不会在 AppDomain.CurrentDomain.GetAssemblies() 中,因为当前域中没有任何内容使用 MyClasses

    您需要加载从MyConvention.assemblyQualifiedTypenames 返回的程序集,然后使用assembly.GetType(name),或者使用Type.GetType 的版本,它允许您指定自己的程序集解析器,如文档中的here(仅在以下情况下才有效)该类包括程序集名称)。

    【讨论】:

    • 如果您查看输出,您会看到当我显式搜索 AppDomain.CurrentDomain.GetAssemblies() 时找到了类 is,其中包含 3 个不同字符串中的任何一个。 Type.GetType() 没有用 3 个不同的字符串中的任何一个找到它。
    • 我会试试你引用的重载,看看是否能让我看到类型。
    【解决方案2】:

    试试这段代码。这避免了使用程序集限定名称,因此没有硬编码版本控制。

    const string myClass = "<Namespace.Class>";
    const string dllName = "<DllName>,"; //Notice the ','
    
    Type myType = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.ToString().StartsWith(dllName)).Select(a => a.GetType(myClass )).FirstOrDefault();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 2010-10-12
      • 2011-04-16
      • 2020-02-16
      • 2013-09-13
      • 2011-01-22
      相关资源
      最近更新 更多