自动确定 MaxLength 并将其用于填充
Automatically determine MaxLength and use it for padding
我有一个模型,其中包含这样定义的一堆字段:
public class Transaction
{
public DateTime R03DateFrom { get; set; }
public DateTime? R03DateTo { get; set; }
[MaxLength(80)]
public string R03Place { get; set; }
[MaxLength(20)]
public string R03Code { get; set; }
// And so on....
}
在某个时候我需要将一些数据导出到固定宽度的文件,如果一个字符串的 MaxLength 为 x,那么在输出文件中它应该总是输出右填充最多 x 的空格字符。
我希望重新使用字符串的 MaxLength 始终在模型中定义这一事实,以便将此信息传递到导出。
目前,一个典型的导出行函数如下所示(ExDateTime 是一种将日期格式化为 yyyyMMddhhmm 格式的扩展方法):
private string GetR03Row()
{
return GetRowCode() + "03" +
R03DateFrom.ExDateTime() +
R03DateTo.ExDateTime() +
(R03Place??"").PadRight(80) +
(R03Code??"").PadRight(20);
}
我想更换线路
(R03Place??"").PadRight(80)
使用 MaxLength 属性的内容。
每个字符串都有一个 MaxLength。
更新:
我采纳了下面的建议并将其变成了扩展方法:
public static string PadToMax<T>(this string source, string propName)
{
PropertyInfo[] props = typeof(T).GetProperties();
var found = props.Where(m => m.Name.Equals(propName));
if (!found.Any()) return source;
var propertyInfo = found.First();
var attrs = propertyInfo.GetCustomAttributes(false);
if (!attrs.Any()) return source;
foreach (var maxLengthAttribute in attrs.OfType<MaxLengthAttribute>())
{
return (source??"").PadRight(maxLengthAttribute.Length);
}
return source;
}
这让我可以使用这个语法来实现我想要的:
// (R03Place??"").PadRight(80) turns into
R03Place.PadToMax<Transaction>(nameof(R03Place))
这很好。如果我可以更改扩展方法以某种方式计算出 "Transaction" 类型和源字符串变量的名称,我会很高兴。但是已经足够接近了。
可以将最大长度保存为私有字段吗?
public class Transaction
{
private int maxLengthPlace = 80
public DateTime R03DateFrom { get; set; }
public DateTime? R03DateTo { get; set; }
[MaxLength(maxLengthPlace)]
public string R03Place { get; set; }
[MaxLength(20)]
public string R03Code { get; set; }
// And so on....
}
然后再使用相同的字段?
(R03Place??"").PadRight(maxLengthPlace)
Olivier 的提议应该可行。
换个方式:
private static void Main(string[] args)
{
var maxLength = GetMaxLengthAttributeValue<Transaction>("R03Place");
Console.WriteLine("R03Place = {0}",maxLength);
maxLength = GetMaxLengthAttributeValue<Transaction>("R03Code");
Console.WriteLine("R03Place = {0}",maxLength);
Console.ReadLine();
}
public static int? GetMaxLengthAttributeValue<T>(string propertyName)
{
PropertyInfo[] props = typeof (T).GetProperties();
var found = props.Where(m => m.Name.Equals(propertyName));
if (!found.Any()) return null;
var propertyInfo = found.First();
var attrs = propertyInfo.GetCustomAttributes(false);
if (!attrs.Any()) return null;
foreach (object attr in attrs)
{
MaxLengthAttribute maxLengthAttribute = attr as MaxLengthAttribute;
if (maxLengthAttribute != null)
{
return maxLengthAttribute.Length;
}
}
return null;
}
将方法放在辅助程序中 class:
//You can use it as:
(R03Place??"").PadRight(YourHelper.GetMaxLengthAttributeValue<Transaction>("R03Place").Value);
// with C# 6, you don't have to hard code the property name
(R03Place??"").PadRight(YourHelper.GetMaxLengthAttributeValue<Transaction>(nameof(R03Place)).Value);
我有一个模型,其中包含这样定义的一堆字段:
public class Transaction
{
public DateTime R03DateFrom { get; set; }
public DateTime? R03DateTo { get; set; }
[MaxLength(80)]
public string R03Place { get; set; }
[MaxLength(20)]
public string R03Code { get; set; }
// And so on....
}
在某个时候我需要将一些数据导出到固定宽度的文件,如果一个字符串的 MaxLength 为 x,那么在输出文件中它应该总是输出右填充最多 x 的空格字符。
我希望重新使用字符串的 MaxLength 始终在模型中定义这一事实,以便将此信息传递到导出。
目前,一个典型的导出行函数如下所示(ExDateTime 是一种将日期格式化为 yyyyMMddhhmm 格式的扩展方法):
private string GetR03Row()
{
return GetRowCode() + "03" +
R03DateFrom.ExDateTime() +
R03DateTo.ExDateTime() +
(R03Place??"").PadRight(80) +
(R03Code??"").PadRight(20);
}
我想更换线路
(R03Place??"").PadRight(80)
使用 MaxLength 属性的内容。
每个字符串都有一个 MaxLength。
更新:
我采纳了下面的建议并将其变成了扩展方法:
public static string PadToMax<T>(this string source, string propName)
{
PropertyInfo[] props = typeof(T).GetProperties();
var found = props.Where(m => m.Name.Equals(propName));
if (!found.Any()) return source;
var propertyInfo = found.First();
var attrs = propertyInfo.GetCustomAttributes(false);
if (!attrs.Any()) return source;
foreach (var maxLengthAttribute in attrs.OfType<MaxLengthAttribute>())
{
return (source??"").PadRight(maxLengthAttribute.Length);
}
return source;
}
这让我可以使用这个语法来实现我想要的:
// (R03Place??"").PadRight(80) turns into
R03Place.PadToMax<Transaction>(nameof(R03Place))
这很好。如果我可以更改扩展方法以某种方式计算出 "Transaction" 类型和源字符串变量的名称,我会很高兴。但是已经足够接近了。
可以将最大长度保存为私有字段吗?
public class Transaction
{
private int maxLengthPlace = 80
public DateTime R03DateFrom { get; set; }
public DateTime? R03DateTo { get; set; }
[MaxLength(maxLengthPlace)]
public string R03Place { get; set; }
[MaxLength(20)]
public string R03Code { get; set; }
// And so on....
}
然后再使用相同的字段?
(R03Place??"").PadRight(maxLengthPlace)
Olivier 的提议应该可行。
换个方式:
private static void Main(string[] args)
{
var maxLength = GetMaxLengthAttributeValue<Transaction>("R03Place");
Console.WriteLine("R03Place = {0}",maxLength);
maxLength = GetMaxLengthAttributeValue<Transaction>("R03Code");
Console.WriteLine("R03Place = {0}",maxLength);
Console.ReadLine();
}
public static int? GetMaxLengthAttributeValue<T>(string propertyName)
{
PropertyInfo[] props = typeof (T).GetProperties();
var found = props.Where(m => m.Name.Equals(propertyName));
if (!found.Any()) return null;
var propertyInfo = found.First();
var attrs = propertyInfo.GetCustomAttributes(false);
if (!attrs.Any()) return null;
foreach (object attr in attrs)
{
MaxLengthAttribute maxLengthAttribute = attr as MaxLengthAttribute;
if (maxLengthAttribute != null)
{
return maxLengthAttribute.Length;
}
}
return null;
}
将方法放在辅助程序中 class:
//You can use it as:
(R03Place??"").PadRight(YourHelper.GetMaxLengthAttributeValue<Transaction>("R03Place").Value);
// with C# 6, you don't have to hard code the property name
(R03Place??"").PadRight(YourHelper.GetMaxLengthAttributeValue<Transaction>(nameof(R03Place)).Value);