自动确定MaxLength并将其用于填充

时间:2015-10-29 00:54:45

标签: c# reflection

我有一个模型,其中包含一系列字段,如下所示:

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))

这很好。我喜欢它,如果我可以改变扩展方法以某种方式计算出“事务”类型和源字符串变量的名称。但是你已经够了。

2 个答案:

答案 0 :(得分:3)

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;
    }

将该方法放在辅助类中:

//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);

答案 1 :(得分:0)

你能将maxlength保存为私有字段吗?

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)