1

我正在尝试使用 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 的已配置实例

我已经根据这篇 SO 帖子完成了所有测试——我是否遗漏了一些基本的东西?

4

2 回答 2

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();
于 2014-10-09T23:25:57.747 回答
1

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

出于类似的原因,它不会AppDomain.CurrentDomain.GetAssemblies()在当前域中使用MyClasses.

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

于 2012-07-01T07:02:56.007 回答