如何使用for循环将AutoMapper配置文件添加到我的映射器配置中?

时间:2019-03-07 14:57:51

标签: c# asp.net dependency-injection automapper

我想加载一堆引用库的自动映射器配置文件,而无需手动键入每个文件。

我正在尝试执行以下步骤:

  1. 从引用的程序集中获取所有配置文件
  2. 将配置文件添加到映射器配置
  3. 注册DI的映射器

第1步有效,但第2步出了问题。

当前代码:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {            
        var container = new UnityContainer();

        var assemblyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies()
            .Where(a => a.Name.StartsWith("OKL_KPS"));

        var assemblies = assemblyNames.Select(an => Assembly.Load(an));

        var loadedProfiles = new List<Type>();
        foreach (var assembly in assemblies)
        {
            var assemblyProfiles = assembly.ExportedTypes.Where(type => type.IsSubclassOf(typeof(Profile)));
            loadedProfiles.AddRange(assemblyProfiles);
        }

        var mapconfig = new MapperConfiguration(cfg =>
        {
            // Magic should happen here
            foreach (var profile in loadedProfiles)
            {
                var resolvedProfile = container.Resolve(profile) as Profile;
                cfg.AddProfile(resolvedProfile);
            }
        });

        container.RegisterInstance<IMapper>(mapconfig.CreateMapper());

        config.DependencyResolver = new UnityResolver(container);

        //routes here
    }
}

我也尝试过cfg.AddProfile((Profile)Activator.CreateInstance(profile.AssemblyQualifiedName, profile.Name).Unwrap());,但这会返回我正在使用它的服务的程序集名称,而不是概要文件所在的库的名称。

修改

在注册步骤期间未加载程序集。为了破解这个问题,每个库中都有一个Dummy类,在注册配置文件之前会对其进行初始化。最佳解决方案不需要这些虚拟类,否则,显式添加每个配置文件会更清洁。

我还尝试将ExportAttribute添加到个人资料中,但这也不起作用。

2 个答案:

答案 0 :(得分:0)

您可以通过列出程序集实例,程序集名称或类型来添加配置文件。

使用名称:

 var mapconfig = new MapperConfiguration(cfg =>
        {
           cfg.AddProfiles("Foo.YourProject.API");
           cfg.AddProfiles("Foo.YourProject.Service");
           cfg.AddProfiles("Foo.YourProject.Repository");
           ...
        });

也请查看官方documentation以获取更多信息。

答案 1 :(得分:0)

documenation中描述了如何在Microsoft DI框架中使用AutoMapper。并在那里简单地转发到相应的NuGet packagean article,它们描述了如何在当前应用程序域中搜索所有打开的类型和配置文件以加载它们。

然后,在您的类中,您只需要将IMapper imapper注入到构造函数中,然后构造函数便可以完成您期望的操作。

我遇到的下一个警告是,在我的services.AddAutoMapper()方法中调用ConfigureServices()之前,并非所有程序集都已加载。但是对于这种情况,我只是添加了一个简单的辅助方法,该方法将在DI开始工作之前被调用:

public static void LoadAllLocalAssemblies()
{
    var entryAssembly = Assembly.GetEntryAssembly();
    var location = entryAssembly.Location;
    var path = Path.GetDirectoryName(location);

    var files = Directory.EnumerateFiles(path, "*.dll");

    foreach (var file in files)
    {
        try
        {
            Assembly.LoadFrom(file);
        }
        catch
        {
        }
    }
}

此后,所有程序集都加载到当前应用程序域中,并且NuGet包将解析所有从Profile派生的类。我的处理程序将IMapper mapper注入到构造函数中,并且可以在我的方法中调用mapper.Map<MyDestination>(mySource),它可以按预期工作。

不需要虚拟类,接口或任何其他东西。