2012-11-16 53 views
1

我正在使用ASP.NET MVC 4C#AutoMapper。在我的global.asax.cs中,我試圖從另一個項目(我的web應用中引用的C#項目)註冊我的映射。從Web項目之外的程序集中獲取類

在另一個項目,我有我的映射,這裏是一個示例類:

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

我想要的只是在給定的命名空間中指定的類的列表。

回答

3

如何獲得我的類在特定的命名空間(從另一個項目以外的其他項目),並使用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 
} 

(如果你可以給你想要做什麼的更多信息,它會更容易以更詳細地幫助您。)

+0

你的類型是什麼意思?這些都是課程。 –

+1

@BrendanVogt:類*是*類型 - 如果你只想要類,使用't.IsClass'作爲另一個過濾器。 –

+0

我的意思是我把什麼放在TheTypeYouKnowAbout的地方? –

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福格特的評論:

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)); 
    } 
} 
+0

從@Jon Skeet的回答添加註釋。 Assembly.GetTypes()加載程序集中包含的所有類型(public,private,internal等)。調用Assembly.GetExportedTypes()將只返回公共類型。 –

+0

我不想指定像EmployeeMapping這樣的類名,因爲還有其他映射類。代碼會太多。我不想指定.dll,因爲如果我在除此之外的其他項目中映射類,會發生什麼? –

+0

@Brendan Vogt,看到我上面的編輯.. –

相關問題