自动捕获随机错误

时间:2013-04-30 15:22:18

标签: asp.net-mvc-3 unity-container automapper

2个月前我问过this problem!问题仍然存在。

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

我的意思是如果程序流程访问Country-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项目)时,错误就消失了。然后,在一个随机的时间,它再次发生。

如果这个问题只发生在开发环境中,这不会是一件大事,但是在发布之后问题仍然存在,所以我遇到了大麻烦。

我搜索了Google,Stackoverflow,Automapper论坛/群组但没有成功。

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

我的项目是使用Automapper 2.2和Unity IoC的MVC 3项目..

同样,我会感谢任何想法,建议或解决方案。

编辑:好的,现在我有了一个线索..我有一个名为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映射的那个。

3 个答案:

答案 0 :(得分: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 :(得分:1)

我最近遇到过类似的问题。事实证明,在同一个AppDomain中运行的代码中有多个AutoMapper.Initialize调用(这是在WCF服务中)。 调用将注册不同的映射。

AutoMapper.Initialize清除以前注册的所有映射,因此当多个线程同时运行时,配置会不时地竞争并抛出错误,同时在单元和集成测试中完全正常运行。

因此,请扫描您的代码库以获取对AutoMapper.Initialize(和AutoMapper.Reset)的调用,并确保只有一个调用。如果您需要在多个步骤中配置AutoMapper,请使用AutoMapper.Configure进行后续步骤。

更多信息here

答案 2 :(得分:0)

对我来说,这个错误与我拨打CreateMap<>()电话的地方有关。我把它放在我的DTO的静态初始化器中。当我将CreateMap<>()电话移动到不太可爱的地方时,一切正常。