我正在尝试创建一个AutoMapper配置文件,该配置文件允许将Dictionary<string, string>
映射到我的DTO,其中每个目标属性或路径都可以在零列或更多列中找到。为了简化下面的复制过程,我使用了DataRow
而不是xunit
。
使用以下类从NuGet的automapper
和public class Person
{
public string Name { get; set; }
}
// Simplified for repro, in reality this is a DataRow in a DataTable
public class Data
{
public IDictionary<string, string> Values { get; set; }
}
开始使用新的.NET Core类库:
[Theory]
[InlineData("name")]
[InlineData("Full name")]
public void Can_find_mapped_column(string columnName)
{
var person = new Person { Name = "John" };
var data = new Data { Values = new Dictionary<string, string> { { columnName, "Johnnie" } } };
var mapper = new MapperConfiguration(c => c.AddProfile(new MyProfile())).CreateMapper();
person = mapper.Map<Data, Person>(data, person);
Assert.Equal("Johnnie", person.Name);
}
[Fact]
public void Can_skip_property()
{
var person = new Person { Name = "John" };
var data = new Data { Values = new Dictionary<string, string> { { "Irrelevant Column", "foobar" } } };
var mapper = new MapperConfiguration(c => c.AddProfile(new MyProfile())).CreateMapper();
person = mapper.Map<Data, Person>(data, person);
Assert.Equal("John", person.Name);
}
然后我尝试至少满足以下单元测试:
public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<Data, Person>()
.ForMember(p => p.Name, o =>
{
o.PreCondition(d => d.Values.ContainsKey("name"));
o.MapFrom(d => d.Values["name"]);
})
.ForMember(p => p.Name, o =>
{
o.PreCondition(d => d.Values.ContainsKey("Full name"));
o.MapFrom(d => d.Values["Full name"]);
})
// Etc.
;
}
}
我已经尝试过此配置文件,但是它不起作用:
MapFrom
我找到了一种解决方法,但是它需要public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<Data, Person>()
.ForMember(p => p.Name, o =>
{
var names = new[] { "name", "Full name", };
o.PreCondition(d => names.Any(n => d.Values.ContainsKey(n)));
o.MapFrom(d => names.Aggregate((string)null, (result, next) => result != null || !d.Values.ContainsKey(next) ? result : d.Values[next]));
})
// Etc.
;
}
}
表达式中相当脆弱的代码:
<div class="page-box">
<h1 class="page-title">用户登录</h1>
<form action="user_login_check.php" method="post" id="form_login" onsubmit="send_form('form_login');return false;">
<div id="form_login_notice" class="alert alert-warning" style="display: none;" ></div>
<div class="form-group">
<input type="text" name="email" placeholder="Email" class="form-control" />
</div>
<div class="form-group">
<input type="password" name="password" placeholder="密码(6-12个字符)" class="form-control" />
</div>
<div class="form-group">
<input type="submit" value="登录" class="btn btn-primary" />
</div>
</form>
</div>
我考虑过this answer with a custom resolver,但是看不到如何通过可能的源名称列表,和,我看不到如何优化这种方法来通过第二次测试
可能我正在尝试使用错误的工具来完成这项工作,而我不应该尝试强迫AutoMapper为我这样做吗?还是有我看不到的选项?