每次我在StackOverflow上寻找AutoMapper时,我都在阅读有关ValueInjecter的内容.
有人能告诉我它们之间的优缺点(性能,功能,API使用,可扩展性,测试)吗?
我在用ASP.NET MVC 3.
有人可以帮我澄清这里发生的事情:
var person = new PersonRepository().Get();
var personViewModel = new PersonViewModel();
personViewModel.InjectFrom<LoopValueInjection>(person)
.InjectFrom<CountryToLookup>(person);
Run Code Online (Sandbox Code Playgroud)
我的Index观点有一个网格.每行都是一个实例CategoryViewModel.所以我所做的是获取所有类别的列表,然后将每个Category类别映射到CategoryViewModel,然后将此ListViewModel列表传递给视图.我会做那样的映射吗?
IEnumerable<Category> categoryList = categoryService.GetAll();
Run Code Online (Sandbox Code Playgroud)
我认为以下内容可行,但事实并非如此:
// Mapping
IList<CategoryViewModel> viewModelList = new List<CategoryViewModel>();
viewModelList.InjectFrom(categoryList);
Run Code Online (Sandbox Code Playgroud) 假设我的DAL(ORM等)中有这个对象
public class Student
{
public string Name {get;set;}
public string Address {get;set;}
public string Phone {get;set;}
public Parent Parent {get;set;}
}
public class Parent
{
public string Name {get;set;}
public string Address {get;set;}
public string Phone {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
我有一个看起来像这样的ViewModel
public class StudentDetailVM
{
public string Name {get;set;}
public string Address {get;set;}
public string Phone {get;set;}
public string ParentName {get;set;}
public string ParentPhone {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
在那种情况下,我需要展平对象.我可以使用Automapper,ValueInjector等工具完成此操作,或者我可以手动执行此操作.如果有许多这样的类要处理,这是一项繁琐的工作,但似乎在这三种方法之间存在性能/开发人员效率权衡.
我在寻找指导时使用Automapper VS Valueinjector VS手动映射.我确定手动映射是最快的,但是多少?
某些场景是否比其他场景慢得多/更快(例如展平等)?
使用混合方法在层之间映射对象是否有意义?
我问的原因是因为创建了一个名为emitmapper的Codeplex项目来解决automapper中的性能问题,我记得看到一条评论说自动化器可能需要花费0.5毫秒来映射一个大类.(需要参考)
我还记得看过一篇文章,该文章介绍了如果用户在70毫秒内加载,而不是90毫秒或更长时间,他们在网站上停留的可能性会更高.(我也在寻找这个链接).如果automapper消耗了我的大部分页面加载时间,加上网络延迟,那么我发现有可能不使用automapper并为我的高容量页面创建手动类,并坚持使用混合方法.
一句话:我会自己运行测试,但是我不太了解.NET内部结构来创建可以用作可重用指南的准确结果.
编辑
这个问题的简单版本是,如果我有一些object o,我将如何检查o是否是某种IEnumerable<string> 用反射实现的类型?最初的问题更具体,但对上述问题的答案也同样好.对不起,如果我在这个问题上提供了太多细节
结束编辑
以下是一个人为的ValueInjecter POC.一切都很好,除了isCollectionMapping最底层的方法.当且仅当源和目标属性都是实现的任何对象时,我试图让它返回true IEnumerable<respectiveTypes>.
我试过IsAssignableFrom,也IsInstanceOfType,但既不似乎工作.
其他一切都有效,因为当我取消注释方法的第二行以明确检查名称"Children"的属性时,它工作正常.
注意 - 我知道此示例存在问题.也就是说,我正在试图检查任何旧的,IEnumerable<>但总是知道足以返回List<>; 在这一点上,它只是一个愚蠢的概念证明.
[TestClass]
public class UnitTest1 {
[TestMethod]
public void TestMethod1() {
List<string> strings = new List<string>();
Subject S = new Subject() {
id = 1,
SubjectName = "S1",
Children = { new Subject() { id = 2, SubjectName = "S1a" },
new Subject() { id = 3, SubjectName = "S1b", …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用AutoMapper深度克隆以下类:
public class MainData
{
public MainData()
{
Details = new List<Detail>();
}
public int Id { get; private set; }
public DateTime LastUpdate { get; private set; }
public IList<Detail> Details { get; private set; }
public int Prop1 { get; set; }
public int Prop2 { get; set; }
public void AddDetail(Detail detail)
{
Details.Add(detail);
}
public void RemoveDetail(Detail detail)
{
Details.Remove(detail);
}
public MainData Clone()
{
Mapper.Reset();
Mapper.CreateMap<MainData, MainData>().ForMember(d => d.Id, o => o.Ignore());
// Mapper.CreateMap<Detail, Detail>().ForMember(d …Run Code Online (Sandbox Code Playgroud) 简而言之:如何成功编辑数据库条目而无需在编辑视图中包含模型的每个字段?
更新
所以我在DB(文章)中有一个项目.我想编辑一篇文章.我编辑的文章有很多属性(Id,CreatedBy,DateCreated,Title,Body).其中一些属性永远不需要更改(如Id,CreatedBy,DateCreated).因此,在我的编辑视图中,我只想要可以更改的字段的输入字段(如标题,正文).当我像这样实现编辑视图时,模型绑定失败.我没有提供输入的任何字段都设置为某个"默认"值(如DateCreated设置为01/01/0001 12:00:00 am).如果我确实为每个字段提供输入,一切正常,文章按预期编辑.我不知道是否正确地说"模型绑定失败"是必要的,如果"如果在编辑视图中没有为它们提供输入字段,则系统会填充包含不正确数据的字段".
如何以这样的方式创建编辑视图:我只需要为可以/需要编辑的字段提供输入字段,以便在调用Controller中的Edit方法时,正确填充DateCreated等字段,而不设置某些默认值,不正确的值?这是我目前的编辑方法:
[HttpPost]
public ActionResult Edit(Article article)
{
// Get a list of categories for dropdownlist
ViewBag.Categories = GetDropDownList();
if (article.CreatedBy == (string)CurrentSession.SamAccountName || (bool)CurrentSession.IsAdmin)
{
if (ModelState.IsValid)
{
article.LastUpdatedBy = MyHelpers.SessionBag.Current.SamAccountName;
article.LastUpdated = DateTime.Now;
article.Body = Sanitizer.GetSafeHtmlFragment(article.Body);
_db.Entry(article).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index", "Home");
}
return View(article);
}
// User not allowed to edit
return RedirectToAction("Index", "Home");
}
Run Code Online (Sandbox Code Playgroud)
编辑视图是否有帮助:
. . .
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Article</legend>
<p>
<input type="submit" value="Save" …Run Code Online (Sandbox Code Playgroud) 我试图找出ValueInjecter,所以我可以在我们自己种植的小ORM中使用它.由于我应该支持DataRow和DataTable映射,我正在尝试为这种类型实现映射器.老实说,文档不够好,我想给它一个机会.也许Omu或该图书馆的其他一些用户会回答.
这是我的DataRow注入器
public class DataRowInjection: KnownSourceValueInjection<DataRow>
{
protected override void Inject(DataRow source, object target)
{
for (var i = 0; i < source.ItemArray.Count(); i++)
{
//TODO: Read from attributes or target type
var activeTarget = target.GetProps().GetByName(source.Table.Columns[i].ToString(), true);
if (activeTarget == null) continue;
var value = source.ItemArray[i];
if (value == DBNull.Value) continue;
activeTarget.SetValue(target, value);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这非常有效.所以这里有一个问题我如何为DataTable实现这个并返回Ienumarable或IList.我期望做的代码片段就像.
public class DataTableInjector : ?????
{
protected override void Inject(DataTable source, IList<T> target) where T : class
{
// Do My Staff
foreach …Run Code Online (Sandbox Code Playgroud) 我的问题是从已从数据库返回的Linq2Sql对象中保护Viewmodel.我们已经在一些领域做到了这一点并且有一个很好的分层模式,但是最新的项目要求使用一些枚举,这引起了全面的麻烦.目前我们从数据库撤回然后使用Automapper将水合(或变平)到我们的View模型中,但是模型中的枚举似乎导致了Automapper的问题.我已经尝试创建自定义resovler,它已满足我所有其他映射要求,但它在此实例中不起作用.
代码示例如下:
public class CustomerBillingTabView{
public string PaymentMethod {get; set;}
...other details
}
public class BillingViewModel{
public PaymentMethodType PaymentMethod {get; set;}
...other details
}
public enum PaymentMethodType {
Invoice, DirectDebit, CreditCard, Other
}
public class PaymentMethodTypeResolver : ValueResolver<CustomerBillingTabView, PaymentMethodType>
{
protected override PaymentMethodType ResolveCore(CustomerBillingTabView source)
{
if (string.IsNullOrWhiteSpace(source.PaymentMethod))
{
source.PaymentMethod = source.PaymentMethod.Replace(" ", "");
return (PaymentMethodType)Enum.Parse(typeof(PaymentMethodType), source.PaymentMethod, true);
}
return PaymentMethodType.Other;
}
}
CreateMap<CustomerBillingTabView, CustomerBillingViewModel>()
.ForMember(c => c.CollectionMethod, opt => opt.ResolveUsing<PaymentMethodTypeResolver>())
Run Code Online (Sandbox Code Playgroud)
我收到以下错误
[ArgumentException: Type provided must be an Enum.
Parameter …Run Code Online (Sandbox Code Playgroud) 如何将属性从对象映射到具有不同属性名称的另一个对象?
我有一个Product看起来像这样的课程:
public class Product : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
视图模型看起来像:
public class ProductSpecificationAddViewModel
{
public int ProductId { get; set; }
public string ProductName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我需要做以下映射:
Product.Id => ProductSpecificationAddViewModel.ProductId
Product.Name =>ProductSpecificationAddViewModel.ProductName
Run Code Online (Sandbox Code Playgroud)
这是我的行动方法:
public ActionResult Add(int id)
{
Product product = productService.GetById(id);
// Mapping
//ProductSpecificationAddViewModel viewModel = new ProductSpecificationAddViewModel();
//viewModel.InjectFrom(product);
return View(viewModel);
}
Run Code Online (Sandbox Code Playgroud)
我该怎么做?
mapping asp.net-mvc asp.net-mvc-3 asp.net-mvc-2 valueinjecter
我一直致力于使用PDFView4Net创建PDF表单的项目.虽然库通常很好,但在使用表单字段(即文本框,复选框等)时,表单创建器是原始的并且缺少基本功能(例如复制/粘贴,对齐,格式化等).
问题:我一直在扩展字段对象的功能,并在复制/粘贴时被绊倒.要做到这一点,我需要一个对象的深层副本,而不需要引用任何原始对象.我通过电子邮件发送给供应商,要求提供有关他们推荐的复制这些对象的方法的信息,他们回复说我需要手工制作每个属性的副本,手动...在桌面上敲打.这些是大类,具有多个嵌入类作为属性,以及UI元素.
问题:是否有任何好的方法可以为不需要序列化的复杂对象执行深层复制,不需要访问或更改源类,也不需要默认构造函数?
我尝试过/审查过的内容:我研究了各种方法来制作一个对象的深层副本并逐个丢弃它们:
编辑:我真的不觉得这个问题是重复的.我已经广泛搜索了一个解决方案,包括标记为重复/原始的帖子,但无法找到满意的解决方案.如上所述,我无权更改我需要复制的类.这折扣了DataContractSerializer,BinaryFormatter和任何其他类型的序列化.这也打破了我使用Activator.CreateInstance看到的反射示例,因为我需要复制的类中大约95%没有带0参数的构造函数.这与我使用ValueInjecter遇到的问题相同.这也使用ICloneable进行折扣.
valueinjecter ×10
automapper ×6
c# ×6
asp.net-mvc ×4
.net ×2
clone ×2
viewmodel ×2
asp.net ×1
deep-copy ×1
emitmapper ×1
enums ×1
list ×1
mapping ×1
reflection ×1