- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
编辑:最初我打算使用 AutoMapper 来实现我的目标,但我不得不了解到 AutoMapper 并非旨在以这种方式工作。它使您可以创建配置文件,但在我的情况下(完全可配置)我需要为每个参数组合一个配置文件,所以我想出了一种自己的方法,请参阅答案。
从 AutoMapper wiki 我学会了创建一个像
这样的简单映射 Mapper.CreateMap<CalendarEvent, CalendarEventForm>().ForMember(dest => dest.Title, opt => opt.MapFrom(src => src.Title));
Mapper.CreateMap<CalendarEvent, CalendarEventForm>().ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date));
Mapper.CreateMap<CalendarEvent, CalendarEventForm>().ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.EventDate.Hour));
Mapper.CreateMap<CalendarEvent, CalendarEventForm>().ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.EventDate.Minute));
对于像这样的两个类
public class CalendarEvent
{
public DateTime EventDate;
public string Title;
}
public class CalendarEventForm
{
public DateTime EventDate { get; set; }
public int EventHour { get; set; }
public int EventMinute { get; set; }
public string Title { get; set; }
}
我现在想知道是否有可能在外部定义映射,即在 XML 文件中,例如
<ObjectMapping>
<mapping>
<src>Title</src>
<dest>Tile</dest>
</mapping>
<mapping>
<src>EventDate.Date</src>
<dest>EventDate</dest>
</mapping>
<mapping>
<src>EventDate.Hour</src>
<dest>EventHour</dest>
</mapping>
<mapping>
<src>EventDate.Minute</src>
<dest>EventMinute</dest>
</mapping>
并由此影响 map 的创建(XML 不是必需的,也可以是其他任何东西)。为简单起见,说类型没有问题,所以 src 和 dest 应该相同,否则失败是可以的。这背后的想法是在应该映射什么以及应该映射到哪里方面非常灵活。我正在考虑反射以根据其名称获取属性值,但这似乎行不通。我也不确定这是否有意义,或者我是否遗漏了一些重要的东西,因此非常感谢您的帮助和想法。
最佳答案
最后,我自己实现了原始需求,尽管我并不需要它(需求已更改)。我会在这里提供代码,以防有人需要它(或多或少作为概念证明,因为仍然可以做很多改进)或者对 XML 感兴趣,请记住,XML 容易出错,这种方法的关键组成部分,属性名称和类型必须完全匹配,否则它将无法工作,但是通过一个小的 GUI 来编辑文件,这应该是可以实现的(我的意思是不手动编辑文件)。
我使用了来自 here 的代码和 here并添加了类 PropertyMapping 来存储从 XML 读取的映射,还添加了类 Foo 和 Bar 来创建嵌套数据结构,以便复制到。
无论如何,这里是代码,也许它可以帮助某些人:
主要内容:
public class Program
{
public static void Main(string[] args)
{
// Model
var calendarEvent = new CalendarEvent
{
EventDate = new DateTime(2008, 12, 15, 20, 30, 0),
Title = "Company Holiday Party"
};
MyObjectMapper mTut = new MyObjectMapper(@"SampleMappings.xml");
Console.WriteLine(string.Format("Result MyMapper: {0}", Program.CompareObjects(calendarEvent, mTut.TestMyObjectMapperProjection(calendarEvent))));
Console.ReadLine();
}
public static bool CompareObjects(CalendarEvent calendarEvent, CalendarEventForm form)
{
return calendarEvent.EventDate.Date.Equals(form.EventDate) &&
calendarEvent.EventDate.Hour.Equals(form.EventHour) &&
calendarEvent.EventDate.Minute.Equals(form.EventMinute) &&
calendarEvent.Title.Equals(form.Title);
}
}
映射器实现:
public class MyObjectMapper
{
private List<PropertyMapping> myMappings = new List<PropertyMapping>();
public MyObjectMapper(string xmlFile)
{
this.myMappings = GenerateMappingObjectsFromXml(xmlFile);
}
/*
* Actual mapping; iterate over internal mappings and copy each source value to destination value (types have to be the same)
*/
public CalendarEventForm TestMyObjectMapperProjection(CalendarEvent calendarEvent)
{
CalendarEventForm calendarEventForm = new CalendarEventForm();
foreach (PropertyMapping propertyMapping in myMappings)
{
object originalValue = GetPropValue(calendarEvent,propertyMapping.FromPropertyName);
SetPropValue(propertyMapping.ToPropertyName, calendarEventForm, originalValue);
}
return calendarEventForm;
}
/*
* Get the property value from the source object
*/
private object GetPropValue(object obj, String compoundProperty)
{
foreach (String part in compoundProperty.Split('.'))
{
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
/*
* Set property in the destination object, create new empty objects if needed in case of nested structure
*/
public void SetPropValue(string compoundProperty, object target, object value)
{
string[] bits = compoundProperty.Split('.');
for (int i = 0; i < bits.Length - 1; i++)
{
PropertyInfo propertyToGet = target.GetType().GetProperty(bits[i]);
propertyToGet.SetValue(target, Activator.CreateInstance(propertyToGet.PropertyType));
target = propertyToGet.GetValue(target, null);
}
PropertyInfo propertyToSet = target.GetType().GetProperty(bits.Last());
propertyToSet.SetValue(target, value, null);
}
/*
* Read XML file from the provided file path an create internal mapping objects
*/
private List<PropertyMapping> GenerateMappingObjectsFromXml(string xmlFile)
{
XElement definedMappings = XElement.Load(xmlFile);
List<PropertyMapping> mappings = new List<PropertyMapping>();
foreach (XElement singleMappingElement in definedMappings.Elements("mapping"))
{
mappings.Add(new PropertyMapping(singleMappingElement.Element("src").Value, singleMappingElement.Element("dest").Value));
}
return mappings;
}
}
我的模型类:
public class CalendarEvent
{
public DateTime EventDate { get; set; }
public string Title { get; set; }
}
public class CalendarEventForm
{
public DateTime EventDate { get; set; }
public int EventHour { get; set; }
public int EventMinute { get; set; }
public string Title { get; set; }
public Foo Foo { get; set; }
}
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public DateTime InternalDate { get; set; }
}
内部映射表示:
public class PropertyMapping
{
public string FromPropertyName;
public string ToPropertyName;
public PropertyMapping(string fromPropertyName, string toPropertyName)
{
this.FromPropertyName = fromPropertyName;
this.ToPropertyName = toPropertyName;
}
}
示例 XML 配置:
<?xml version="1.0" encoding="utf-8" ?>
<ObjectMapping>
<mapping>
<src>Title</src>
<dest>Title</dest>
</mapping>
<mapping>
<src>EventDate.Date</src>
<dest>EventDate</dest>
</mapping>
<mapping>
<src>EventDate.Hour</src>
<dest>EventHour</dest>
</mapping>
<mapping>
<src>EventDate.Minute</src>
<dest>EventMinute</dest>
</mapping>
<mapping>
<src>EventDate</src>
<dest>Foo.Bar.InternalDate</dest>
</mapping>
</ObjectMapping>
关于c# - 如何在代码外部定义 AutoMapper 映射,即在 XML 文件中或使用不同的方法进行完全可配置的对象映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19179459/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!