1

我正在使用ASP.NET MVC 4,C#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

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

4

2 回答 2

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
}

(如果您可以提供有关您正在尝试做的事情的更多信息,那么更详细地帮助您会更容易。)

于 2012-11-16T07:43:46.517 回答
0

调用时Assembly.GetAssembly(typeof(string)),它会加载 mscorlib.dll 中的类型,并且您提供的 linq 查询不会返回任何内容。您需要使用typeof(EmployeeMapping).Assemblyor加载程序集Assembly.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));
    }
}
于 2012-11-16T07:50:47.617 回答