donnytian / Npoi.Mapper

Use this tool to import or export data with Excel file. The tool is a convention based mapper between strong typed object and Excel data via NPOI.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot apply TryTake if there is error when parsing Enum

VAllens opened this issue · comments

commented

Get attribute value as friendly display name if property has DisplayName attribute.

Or you design a custom attribute enhancement class that provides a custom friendly display name, column display order, and so on.

Or does Npoi.Mapper already have a similar function? Do you have a better idea?

Sample data model code:

public class CatalogCareViewModel
{
	/// <summary>
	/// ISO/国际标准
	/// </summary>
	public virtual string ISO { get; set; }

	/// <summary>
	/// German/德语
	/// </summary>
	[DisplayName("German")]
	public virtual string DE { get; set; }

	/// <summary>
	/// English/英语
	/// </summary>
	[DisplayName("English")]
	public virtual string EN { get; set; }

	/// <summary>
	/// French/法语
	/// </summary>
	[DisplayName("French")]
	public virtual string FR { get; set; }

	/// <summary>
	/// Russion/俄语
	/// </summary>
	[DisplayName("Russion")]
	public virtual string RU { get; set; }

	/// <summary>
	/// Italian/意大利语
	/// </summary>
	[DisplayName("Italian")]
	public virtual string IT { get; set; }

	/// <summary>
	/// Dutch/荷兰语
	/// </summary>
	[DisplayName("Dutch")]
	public virtual string NL { get; set; }

	/// <summary>
	/// Norwegian/挪威
	/// </summary>
	[DisplayName("Norwegian")]
	public virtual string NO { get; set; }
}

Sample excel sheet table

ISO German English French Russion Italian Dutch Norwegian
value1 value2 value3 value4 value5 value6 value7 value8
value1 value2 value3 value4 value5 value6 value7 value8
value1 value2 value3 value4 value5 value6 value7 value8

不好意思, 有点看不太懂, 用中文好吗?

commented

我大体看了一下,你的组件是支持双向字段名映射的,现在这个已经没问题了。

但又有另外一个问题。
我调用了你的public static Mapper Map(this Mapper mapper, string columnName, Expression<Func<T, object>> propertySelector,
Func<IColumnInfo, object, bool> tryTake = null,
Func<IColumnInfo, object, bool> tryPut = null)方法。
想要实现导入时的枚举值自定义转换。

举例:###

枚举代码:####

public enum Category
{
	[Description("Additional Care")]
	AdditionalCare,
	[Description("Bleach")]
	Bleach,
	[Description("Dry & Wring")]
	DryWring,
	[Description("Dry Clean")]
	DryClean,
	[Description("Iron")]
	Iron,
	[Description("Wash")]
	Wash
}

Excel表格里是这样的枚举值,比如有以下三条数据

Category
Additional Care
Bleach
Dry & Wring

导入过程没有任何异常。

var list = mapper.Take<TModel>().Select(t => t.Value).ToList();

list得到三条为null的数据。
调试过程发现,在这里发生异常:

public static bool TryGetCellValue(ICell cell, Type targetType, out object value)
......
    value = Enum.Parse(targetType, cell.NumericCellValue.ToString(CultureInfo.InvariantCulture));
......

Take方法返回的对象有错误信息.

枚举值目前是严格从名字来parse的, 并没有取相应的attribute, 因为

  1. 相关的attribute比较多, 包括Display, DisplayName, Description等
  2. 上面这些attribute的值不能保证唯一性, 取哪一个的值都可能会导致unexpected result,给查找问题增加难度.

你的例子可以用自定义TryTake 方法解决. 首页有例子.

mapper.Map<Sample>("columnA", o => o.MyEum, (column, o)=>
{
// custom logic to take value from cell.
}, null);
commented

谢谢,是的,我就是定义了TryTake方法后报的异常。

mapper.Map<CatalogCareViewModel>("Category",
	t => t.Category,
	(column, target) =>
	{
		string value = column.CurrentValue.NullableToString(); //如果为null,返回string.Empty;
		//枚举值为Key,枚举描述为Value
		var key = categories.Where(t => t.Value == value).Select(t => t.Key).FirstOrDefault();
		if (key == null) //如果为null,表示这不是一个合法的枚举描述
		{
			return false;
		}

		((CatalogCareViewModel) target).Category = (CareCategory) Enum.Parse(typeof(CareCategory), key);

		return true;
	},
	(column, source) =>
	{
		//填充枚举描述
		column.CurrentValue = ((CatalogCareViewModel) source).Category.GetDescription();

		return true;
	});

你的

private static void LoadRowData(IEnumerable<ColumnInfo> columns, IRow row, object target, IRowInfo rowInfo)

方法内部
image
走到MapHelper.TryGetCellValue方法抛出异常,代码不再继续往下走,而是直接跳到catch块。
意味着即便我定义了TryTake处理逻辑,它也不会执行。
所以我觉得你应该把TryTake是否为null的判断以及执行放在MapHelper.TryGetCellValue方法之前。

commented

对于枚举的处理,我觉得应该增加try catch处理,使程序尽可能的健壮,以及延后引发异常。
image
这样处理,当遇到我这种情况,如果我定义了TryTake,程序将顺利执行。
如果我没有定义TryTake,程序延后到这里引发异常。
image

commented

Hi, Donny.
还记得之前说过的自动化发布NuGet包吗?完全可以在AppVeyor上做到。
每次git push触发AppVeyor构建并且测试通过后发布小版本(如:3.1.0.yyyy)到NuGet
tag发布常规版本(如:3.1.x.yyyy)到NuGet
这个过程涉及到的密钥/token等安全信息,可以通过环境变量传入,以及使用AppVeyor自带的Encrypt加密,防止泄漏。