Search code examples
c#stringbuilder

Build the string dynamically based on the length in c#


My aim is to generate a string. which has following conditions.

First i will take an empty string and start building the string based on length.

Example:

I have an empty string "".

In the first step i want to add a string till 8 characters, means first my string is "" then till 8 characters my string should contain the value Hiwor so finally my string will be Hiwor if there is no value empty value should be padded in the string.

In the second step i want to add the string meena till 10 positions , so my final string should be Hiwor meena. In this way i want to build my string. Ho can i achieve this. Can you please help me.

Sample: initial string ""

first step adding string Hiwor till 8 positions,

so final string should be Hiwor

second step adding string meena till 10 postions

so final string should be Hiwor meena .

Till now i tried like this

 Dictionary<string, Int16> transLine = new Dictionary<string, Int16>();

            transLine.Add("ProductCode", 1);

            transLine.Add("ApplicantFirstName", 12);

            transLine.Add("ApplicantMiddleInitial", 1);

            transLine.Add("partner", 1);

            transLine.Add("employee", 8);

            List<string> list = new List<string>();
            list.Add("grouplife");
            list.Add("meena");
            list.Add("d");
            list.Add("yes");
            list.Add("yes");

            StringBuilder sb = new StringBuilder();
            foreach (var listItem in list)
            {
                foreach (var item in transLine)
                {
                    if (listItem == item.Key)
                    {
                        var length = item.Value;
                        sb.Insert(length, item.Key);
                    }
                }
            }

but it is throwing me an exception.Index was out of range. Must be non-negative and less than the size of the collection.


Solution

  • Firstly define an extension method for StringBuilder:

    public static class StringBuilderExtensions
    {
        public static void AppendPadded(this StringBuilder builder, string value, int length);
        {
            builder.Append($"{value}{new string(' ', length)}".Substring(0, length));
        }
        public static void AppendPadded(this StringBuilder builder, int value, int length);
        {
            builder.Append($"{new string('0', length)}{value}".Reverse().ToString().Substring(0, length).Reverse().ToString());
        }
    }
    

    Then use:

    StringBuilder builder = new StringBuilder();
    builder.AppendPadded("Hiwor", 8);
    builder.AppendPadded("meena", 10);
    return builder.ToString();
    

    Or with your example:

    foreach (string item in list)
        builder.AppendPadded(item, transLine[item]);
    

    EDIT: Ok, so looks like you want to be able to define a format then build the string using it. Try:

    (you will need to reference System.ComponentModel.DataAnnotations and System.Reflection for this)

    public abstract class AnItem
    {
        private static int GetLength(PropertyInfo property)
        {
            StringLengthAttribute attribute = property.GetCustomAttributes(typeof(StringLengthAttribute), true).FirstOrDefault() as StringLengthAttribute;
            if (attribute == null)
                throw new Exception($"StringLength not specified for {property.Name}");
            return attribute.MaxLength();
        }
        private string GetPropertyValue(PropertyInfo property)
        {
            if (property.PropertyType == typeof(string))
                return property.GetValue(this);
            else if (property.PropertyType == typeof(int))
                return property.GetValue(this).ToString();
            else
                throw new Exception($"Property '{property.Name}' is not a supported type");
        }
        private static void SetPropertyValue(object item, PropertyInfo property, string value)
        {
            if (property.PropertyType == typeof(string))
                property.SetValue(item, value, null);
            else if (property.PropertyType == typeof(int))
                property.SetValue(item, int.Parse(value), null);
            else
                throw new Exception($"Property '{property.Name}' is not a supported type");
        }
        public string GetPaddedString()
        {
            StringBuilder builder = new StringBuilder();
            PropertyInfo[] properties = GetType().GetProperties();
            foreach (PropertyInfo property in properties)
                builder.AppendPadded(GetPropertyValue(property), GetLength(property));
            return builder.ToString();
        }
        public static T CreateFromPaddedString<T>(string paddedString) where T : AnItem, new()
        {
            T item = new T();
            int offset = 0;
            PropertyInfo[] properties = typeof(T).GetProperties();
            foreach (PropertyInfo property in properties)
            {
                int length = GetLength(property);
                if (offset + length > paddedString.Length)
                    throw new Exception("The string is too short");
                SetPropertyValue(item, property, paddedString.Substring(offset, length)));
                offset += length;
            }
            if (offset < paddedString.Length)
                throw new Exception("The string is too long");
            return item;
        }
    }
    public class MyItem : AnItem
    {
        [StringLength(1)]
        public string ProductCode { get; set; }
    
        [StringLength(12)]
        public string ApplicantFirstName { get; set; }
    
        [StringLength(1)]
        public string ApplicantMiddleInitial { get; set; }
    
        [StringLength(1)]
        public string Partner { get; set; }
    
        [StringLength(8)]
        public string Employee { get; set; }
    }
    

    Then use it:

    MyItem item = new MyItem
    {
        ProductCode = "grouplife",
        ApplicantFirstName = "meena",
        ApplicantMiddleInitial = "d",
        Partner = "yes",
        Employee = "yes"
    };
    
    string paddedString = item.GetPaddedString();
    

    And to read a string to get an item:

    MyItem item = AnItem.CreateFromPaddedString<MyItem>(paddedString);