Type.GetType没有按名称查找类型

时间:2012-07-01 04:47:49

标签: c# reflection structuremap

我正在尝试使用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, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Type found for reflection by assembly qualified name: False
Type found by assembly qualified name: False
Type found by search: True
MyClasses.Class2
Type found by full name: False
Type found by search: True
Class2
Type found by name: False
Type found by search: True

Type instance retrieved from StructureMap: True

Class2 (MyClasses.Class2)                60eb30ad-ae50-413d-884f-04743ea3148c
  Configured Instance of MyClasses.Class2, MyClasses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
                                         60eb30ad-ae50-413d-884f-04743ea3148c
  Configured Instance of MyClasses.Class2, MyClasses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

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

2 个答案:

答案 0 :(得分:1)

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

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

您需要加载从MyConvention.assemblyQualifiedTypenames返回的程序集,然后使用assembly.GetType(name),或使用Type.GetType版本,它允许您指定自己的程序集解析程序,如{{3} (仅当类包含程序集名称时才有效。)

答案 1 :(得分:1)

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

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