从Web项目之外的程序集中获取类

时间:2012-11-16 07:39:49

标签: c# asp.net asp.net-mvc asp.net-mvc-4 automapper

我正在使用ASP.NET MVC 4C#AutoMapper。在我的global.asax.cs中,我试图从另一个项目(我的网络应用程序中引用的C#项目)注册我的映射。

在这个其他项目中,我有我的映射,这是一个示例类:

namespace MyProject.Web.Core.Mappings
{
     public class EmployeeMapping
     {
          public EmployeeMapping()
          {
               Mapper.CreateMap<Employee, EmployeeInfoViewModel>();
          }
     }
}

在我的global.asax.cs中,我有一个方法,我想加载这些映射。下面的代码我上线了,但它没有拿起我的映射类,在这种情况下是EmployeeMapping:

protected void AutoMapperConfig()
{
     string mappingNamespace = "MyProject.Web.Core.Mappings";

     var q = from t in Assembly.GetAssembly(typeof(string))
             where t.IsClass && t.Namespace == mappingNamespace
             select t;

     q.ForEach(t => Debug.WriteLine(t.Name));
}

如何在特定命名空间(来自Web项目以外的其他项目)中获取我的课程并使用Activator.CreateInstance

我想要的只是给定命名空间中指定的类的列表。

2 个答案:

答案 0 :(得分:3)

  

如何在特定命名空间(从Web项目以外的其他项目中)获取我的类并使用Activator.CreateInstance?

假设您知道程序集中的一个类型,您可以使用:

var types = typeof(TheTypeYouKnowAbout).Assembly.GetTypes()
                .Where(t => t.Namespace == "TheNamespaceYouWant");
                // Possibly add more restrictions, e.g. it must be
                // public, and a class rather than an interface, and
                // must have a public parameterless constructor...
foreach (var type in types)
{
    // Do something with the type
}

(如果您可以提供有关您尝试执行的操作的详细信息,则可以更轻松地更详细地帮助您。)

答案 1 :(得分:0)

调用Assembly.GetAssembly(typeof(string))时,它会加载mscorlib.dll中的类型,并且不会从您提供的linq查询中返回任何内容。您需要使用typeof(EmployeeMapping).AssemblyAssembly.GetAssembly(typeof(EmployeeMapping))Assembly.LoadFrom("YourAssemblyName.dll")加载程序集,以查询该特定程序集的类型。

编辑:

进一步回答你的问题......假设你知道负责映射的所有类型以及它们所包含的程序集。

protected void AutoMapperConfig()
{
    const string mappingNamespace = "MyProject.Web.Core.Mappings";

    //There are ways to accomplish this same task more efficiently.
    var q = (from t in Assembly.LoadFrom("YourAssemblyName.dll").GetExportedTypes()
             where t.IsClass && t.Namespace == mappingNamespace
             select t).ToList();

    //Assuming all the types in this namespace have defined a
    //default constructor. Otherwise, this iterative call will
    //eventually throw a TypeLoadException (I believe) because
    //the arguments for any of the possible constructors for the
    //type were not provided in the call to Activator.CreateInstance(t) 
    q.ForEach(t => Activator.CreateInstance(t));
}

但是,如果您在Web项目中引用程序集......如果在编译时未知类型,我将使用下面的或某种IoC / DI框架来实例化映射类。

protected void AutoMapperConfig()
{
    Mapper.CreateMap<Employee, EmployeeInfoViewModel>();
    //Repeat the above for other "mapping" classes.
    //Mapper.CreateMap<OtherType, OtherViewModel>();
}

编辑@Brendan Vogt首先评论:

public interface IMappingHandler
{
}

//NOTE: None of this code was tested...but it'll be close(ish)..

protected void AutoMapperConfig()
{
    //If the assemblies are located in the bin directory:
    var assemblies = Directory.GetFiles(HttpRuntime.BinDirectory, "*.dll");

    //Otherwise, use something like the following:
    var assemblies = Directory.GetFiles("C:\\SomeDirectory\\", "*.dll");

    //Define some sort of other filter...a base type for example.
    var baseType = typeof(IMappingHandler);

    foreach (var file in assemblies)
    {
        //There are other ways to optimize this query.
        var types = (from t in Assembly.LoadFrom(file).GetExportedTypes()
                     where t.IsClass && !t.IsAbstract && baseType.IsAssignableFrom(t)
                     select t).ToList();

        //Assuming all the queried types defined a default constructor.
        types.ForEach(t => Activator.CreateInstance(t));
    }
}