Skip to content

Instantly share code, notes, and snippets.

@mastoj
Created June 19, 2012 14:32
Show Gist options
  • Save mastoj/2954528 to your computer and use it in GitHub Desktop.
Save mastoj/2954528 to your computer and use it in GitHub Desktop.
Simple generic output formatter
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FileGenerator
{
class Program
{
static void Main(string[] args)
{
var items = new List<DemoClass>();
for(int i = 0; i < 10; i++)
{
items.Add(new DemoClass(DateTime.Now.AddDays(1), i, i.ToString()));
}
var formatter = new OutputFormatter();
var formatDescription = new FormatDescription<DemoClass>()
.With(y => y.SomeNumber, 0, 10, y => y.ToString("0000000000"))
.With(y => y.SomeString, 10, 4, y => y.PadRight(4, 'H'))
.With(y => y.Time, 14, 8, y => y.ToString("yyyyMMdd"));
var output = formatter.FormatOutput(items, formatDescription);
foreach (var item in output)
{
Console.WriteLine("|" + item + "|");
}
Console.ReadLine();
}
}
class DemoClass
{
public DemoClass(DateTime time, int someNumber, string someString)
{
Time = time;
SomeNumber = someNumber;
SomeString = someString;
}
public DateTime Time { get; set; }
public int SomeNumber { get; set; }
public string SomeString { get; set; }
}
public class OutputFormatter
{
public IEnumerable<string> FormatOutput<TToFormat>(IEnumerable<TToFormat> items, FormatDescription<TToFormat> formatDescription)
{
foreach (var item in items)
{
yield return formatDescription.FormatItem(item);
}
}
}
public class FormatDescription<T>
{
private List<FormatStep<T>> _formatSteps = new List<FormatStep<T>>();
public FormatDescription<T> With<TMember>(Expression<Func<T, TMember>> memberToFormat, int startPos, int length, Func<TMember, string> formatFunction = null)
{
Func<dynamic, string> dynamicFormatFunction = y => formatFunction(y);
var convertedMemberToFormat = ConvertReturnExpression(memberToFormat);
this.AddFormatStep(new FormatStep<T>(convertedMemberToFormat, startPos, length, dynamicFormatFunction));
return this;
}
private static Func<dynamic, string> ConvertInputExpression(Func<object, string> formatFunction)
{
throw new NotImplementedException();
}
private void AddFormatStep(FormatStep<T> formatStep)
{
_formatSteps.Add(formatStep);
}
public string FormatItem(T itemToFormat)
{
StringBuilder result = new StringBuilder();
foreach (var formatStep in _formatSteps)
{
var valueToInsert = formatStep.MemberToFormat.Compile().Invoke(itemToFormat);
result.Insert(formatStep.StartPos, formatStep.FormatFunction(valueToInsert));
}
return result.ToString();
}
// This is the method you want, I think
public static Expression<Func<TInput, object>> ConvertReturnExpression<TInput, TOutput>
(Expression<Func<TInput, TOutput>> expression)
{
// Add the boxing operation, but get a weakly typed expression
Expression converted = Expression.Convert
(expression.Body, typeof(object));
// Use Expression.Lambda to get back to strong typing
return Expression.Lambda<Func<TInput, object>>
(converted, expression.Parameters);
}
private class FormatStep<T>
{
public Expression<Func<T, object>> MemberToFormat { get; set; }
public int StartPos { get; set; }
public int Length { get; set; }
public Func<dynamic, string> FormatFunction { get; set; }
public FormatStep(Expression<Func<T, object>> memberToFormat, int startPos, int length, Func<dynamic, string> formatFunction)
{
MemberToFormat = memberToFormat;
StartPos = startPos;
Length = length;
FormatFunction = formatFunction;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment