【问题标题】:Injecting settings into AutoMapper profile将设置注入 AutoMapper 配置文件
【发布时间】:2016-08-08 09:04:02
【问题描述】:

我正在使用 asp.net 核心来实现 REST 服务,它带有一个实体框架作为 ORM、开箱即用的依赖注入和 AutoMapper 来将我的数据模型转换为视图模型。 我的数据模型如下所示:

public class Entity{
   [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int EntityId {get;set;}
   [StringLength(50)]
   public string Name {get;set;}
   [StringLength(4000)]
   public string EntityMetadata {get;set;}
}

public class EntityMetadata{
   public string Property {get;set;}
   public int OtherProperty {get;set;}
}

public class EntityViewModel{
   public string Name {get;set;}
   public EntityMetadata EntityMetadata {get;set;}
}

为了灵活性,我将元数据作为 JSON 格式的字符串存储在数据库中,但希望将其作为强类型模型公开给客户端。为此,我创建了一个 AutoMapper 配置文件。

public class EntityProfile : Profile{
  public EntityProfile(JsonSerializerSettings settings) : {
     CreateMap<EntityViewModel,Entity>
        .ForMember(e=>e.EntityMetadata, m=>m.ResolveUsing(
            c=>JsonConvert.SerializeObject(c.EntityMetadata, settings)))
  }
}

我面临的问题是我无法弄清楚如何配置 AutoMapper 和 MVC,以便它们共享同一个 JsonSerializerSettings 实例。

public void ConfigureServices(IServiceCollection services){
   var mvcBuilder = services.AddMvc();
   mvcBuilder.AddJsonOptions(options => {
            // options.SerializerSettings has no setter
            // and this code is run after ConfigureServices is finished
            // so I cannot extract or assign serializerSettings instance here
            options.SerializerSettings.ConfigureForNodaTime( DateTimeZoneProviders.Tzdb);
            options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
            // configuring AutoMapper here does not work either
        });
        var mapperConfiguration = new MapperConfiguration(config =>
        {
            // how to get this serializerSettings from AddJsonOptions???
            config.AddProfile(new EntityProfile(serializerSettings));
        });

        var mapper = mapperConfiguration.CreateMapper();
        services.AddSingleton(typeof(IMapper), mapper);
}

更新: 为了避免代码重复,我最终做了以下操作:

    private JsonSerializerSettings ConfigureJsonSettings(JsonSerializerSettings settings)
    {
        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        settings.NullValueHandling = NullValueHandling.Ignore;
        settings.MissingMemberHandling = MissingMemberHandling.Error;
        settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
        return settings;
    }

然后调用两次:

mvcBuilder.AddJsonOptions(options => ConfigureJsonSettings(options.SerializerSettings));
ConfigureMapper(services, ConfigureJsonSettings(new JsonSerializerSettings()));

我必须复制 settings.ContractResolver 等配置以确保它们相同。所以我还是想知道是否有更好的方法来做这个软配置。

【问题讨论】:

  • 使用mvcBuilder.AddJsonOptions方法内serializerSettings中的值作为ConfigureForNodaTime等的参数

标签: entity-framework dependency-injection json.net asp.net-core automapper


【解决方案1】:

您可以在AddJsonOptions 方法之外声明您的JsonSerializerSettings,然后在您的MapperConfiguration 的全局上下文中使用它。

例子:

var serializerSettings = new JsonSerializerSettings();
serializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
serializerSettings.MissingMemberHandling = MissingMemberHandling.Error;

mvc.AddJsonOptions(options =>
{
    // have to repeat this because it's an extension method                  
    options.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
    // can get this from the declared settings
    options.SerializerSettings.MissingMemberHandling = serializerSettings.MissingMemberHandling;
});

var mapperConfiguration = new MapperConfiguration(config =>
{
    // use the already declared settings
    config.AddProfile(new EntityProfile(serializerSettings));
});

这不是一个很好的解决方案,因为有重复的代码,但这是启动配置代码,所以有一个额外的 JsonSerializerSettings 实例浮动不会破坏您的应用程序。如果选项上的SerializerSettings 属性是可设置的会更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 2018-01-19
    • 1970-01-01
    • 2018-07-04
    • 2012-09-07
    • 2020-03-31
    • 1970-01-01
    相关资源
    最近更新 更多