2013-04-30 133 views
1

2个月前我有问题this problem!问题依然存在。Automapper随机错误

我不打算在这里复制/粘贴相同的问题,因为我发现错误不是针对特定的实体-DTO映射,而是针对任何首先在控制器中的实体-DTO。

我的意思是如果程序流程命中乡村CountryDto,错误说:

Missing type map configuration or unsupported mapping. 

Mapping types: 
Country -> CountryDTO 
MyApp.Domain.BoundedContext.Country -> MyApp.Application.BoundedContext.CountryDTO 

Destination path: 
List`1[0] 

Source value: 
MyApp.Domain.BoundedContext.Country 

或者,如果有第一手的账户检查,错误说:

Missing type map configuration or unsupported mapping. 

Mapping types: 
Account -> AccountDTO 
MyApp.Domain.BoundedContext.Account -> MyApp.Application.BoundedContext.AccountDTO 

Destination path: 
AccountDTO 

Source value: 
MyApp.Domain.BoundedContext.Account 

我还发现,当我重建我的N层解决方案的表示层(在这种情况下,它是一个MVC 3项目)时,错误消失了。然后,在随机时间,它又发生了。

如果这个问题只发生在开发环境中,这不会有什么大不了,但发布后问题仍然存在,所以我很麻烦。

我已经通过谷歌搜索,Stackoverflow,Automapper论坛/组没有成功。

我也用Mapper.AssertConfigurationIsValid()测试了映射,一切都很好。

我的项目是一个MVC 3项目,Automapper 2.2和统一的IoC ..

而且,我将不胜感激任何想法,建议或解决方案。

编辑:好的,现在我有一个线索..我有一个名为ManagementProfile的配置文件,我的所有映射都完成了。在AutomapperTypeAdapterFactory()我有这样的代码:

public AutomapperTypeAdapterFactory() 
    { 
     //Scan all assemblies to find an Auto Mapper Profile 
     var profiles = AppDomain.CurrentDomain.GetAssemblies() 
           .SelectMany(a => a.GetTypes()) 
           .Where(t => t.BaseType == typeof(Profile)); 

     Mapper.Initialize(cfg => 
     { 
      foreach (var item in profiles) 
      { 
       if (item.FullName != "AutoMapper.SelfProfiler`2") 
        cfg.AddProfile(Activator.CreateInstance(item) as Profile); 
      } 
     }); 
    } 

我发现,通常情况下,profiles变量保存ManagementProfile 有时无法得到的信息,并说"Enumeration yielded no results"和我在这个问题提到的异常。

随着进一步的调查,我看到,当一切都很好的AppDomain.CurrentDomain.GetAssemblies()加载85程序集,另一方面,当我得到例外它只加载了41个程序集,很明显,其中一个缺少的程序集是持有DTO映射。

+0

由于您在Application_Start上启动引导程序,我不知道是否有一些特定条件在启动时抛出异常,以至于无法在启动时完成“AutoMapper”配置。是否有可能将Application_Start中的某些异常从某处隐藏?如果映射配置没有发生,因为应用程序以静默方式启动失败,这可能是缺少映射的原因 - Mapper.AssertConfigurationIsValid将对没有映射的配置返回true – Charleh 2013-04-30 15:32:01

回答

2

好吧,我终于想通了。 :

AppDomain.CurrentDomain.GetAssemblies() 

我的代码段有时不会得到我的映射程序集,所以当它缺少我得到一个错误。通过强制应用程序找到所有程序集解决了我的问题来替换此代码。

感谢您的回复。

编辑:由于Andrew Brown询问解决方案的代码,我意识到我没有包含源代码片段。这里是AssemblyLocator:

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.IO; 
using System.Linq; 
using System.Reflection; 
using System.Web; 
using System.Web.Compilation; 

public static class AssemblyLocator 
{ 
    private static readonly ReadOnlyCollection<Assembly> AllAssemblies; 
    private static readonly ReadOnlyCollection<Assembly> BinAssemblies; 

    static AssemblyLocator() 
    { 
     AllAssemblies = new ReadOnlyCollection<Assembly>(
      BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList()); 

     IList<Assembly> binAssemblies = new List<Assembly>(); 

     string binFolder = HttpRuntime.AppDomainAppPath + "bin\\"; 
     IList<string> dllFiles = Directory.GetFiles(binFolder, "*.dll", 
      SearchOption.TopDirectoryOnly).ToList(); 

     foreach (string dllFile in dllFiles) 
     { 
      AssemblyName assemblyName = AssemblyName.GetAssemblyName(dllFile); 

      Assembly locatedAssembly = AllAssemblies.FirstOrDefault(a => 
       AssemblyName.ReferenceMatchesDefinition(
        a.GetName(), assemblyName)); 

      if (locatedAssembly != null) 
      { 
       binAssemblies.Add(locatedAssembly); 
      } 
     } 

     BinAssemblies = new ReadOnlyCollection<Assembly>(binAssemblies); 
    } 

    public static ReadOnlyCollection<Assembly> GetAssemblies() 
    { 
     return AllAssemblies; 
    } 

    public static ReadOnlyCollection<Assembly> GetBinFolderAssemblies() 
    { 
     return BinAssemblies; 
    } 
} 

因此,而不是使用AppDomain.CurrentDomain.GetAssemblies(),我打电话的GetAssemblies()所提供的辅助类的方法,如:

//Scan all assemblies to find an Auto Mapper Profile 
//var profiles = AppDomain.CurrentDomain.GetAssemblies() 
//      .SelectMany(a => a.GetTypes()) 
//      .Where(t => t.BaseType == typeof(Profile)); 
var profiles = AssemblyLocator.GetAssemblies(). 
           SelectMany(a => a.GetTypes()). 
           Where(t => t.BaseType == typeof(Profile)); 
+1

你是如何着手“强制应用程序查找所有程序集”的?提前致谢。 – 2017-09-07 16:24:49

+0

答案已更新@AndrewBrown – 2017-11-02 16:37:31

1

我最近有类似的问题。原来在同一个AppDomain中运行的代码中有多个调用AutoMapper.Initialize(这是在WCF服务中)。 这些调用会注册不同的映射。

AutoMapper.Initialize清除任何以前注册的映射,所以当多个线程同时运行时,配置会竞争,并在单元和集成测试中正常工作时出现错误。

因此,请扫描您的代码库以拨打AutoMapper.Initialize(和AutoMapper.Reset),并确保只有一个呼叫。如果您需要分几步配置AutoMapper,请在后续步骤中使用AutoMapper.Configure

更多信息here

+0

我没有直接初始化Automapper。 'public static void Initialise() { var container = BuildUnityContainer(); DependencyResolver.SetResolver(new UnityDependencyResolver(container));并且在BuildUnityContainer代码中,我将适配器设置为'_container.RegisterType (新的ContainerControlledLifetimeManager()); '和工厂作为'var typeAdapterFactory = _container.Resolve (); TypeAdapterFactory.SetAdapter(typeAdapterFactory);' – 2013-05-02 11:02:42

0

对于我这个错误与我把我的CreateMap<>()电话放在哪里有关。我已经把它放在我的DTO的静态初始化器中。当我将CreateMap<>()呼叫移到不太可爱的地方时,一切正常。