C # Lambda + Extensions + Fluent - How would I do this?

I want to be able to create Transformation classes that take a given object, perform a series of transformations on it (that is, change property values), and track the conversions that have been completed. The conversion will depend on the properties of the provided object.

I want to be able to apply transformation rules (which are finite and commin) within a given transformation class using a free style interface.

At a high level, I understand that I will most likely have ITransformer, ITransformationRule and ITransformationResult, as well as several other objects for this to happen.

How I wish the code worked when creating the conversion classes ...

public OfflinePersonToOnlineTransformation : TransformerBase<Person> { public OfflinePersonToOnlineTransformation() { Transform(x => x.PersonClassification) .WhenCreatedBefore("1/1/2000") .ClassifyAs("Online"); } } 

I understand that my TransformerBase will need to implement the Transform method, which accepts Func or Expression, and I understand that it will need to store the ITransformationRules collection. I also understand that I will most likely use extension methods for the WhenCreatedBefore and ClassifyAs methods.

The problem is that I cannot figure out how to make it all work. I looked at the source code for Fluent Validation.NET, as it does validation in this way, but complexity kills me. I am looking for a tutorial that covers this, or someone to describe it in a way that is pretty simple.

Thanks in advance.

+4
source share
3 answers

Not quite sure why you want to go for all of this when linq does most of this for you:

 IEnumerable<Person> somePeople; // from wherever somePeople.Where(x => x.CreateDate < new DateTime(2000,1,1)) .ForEach(x => x.PersonClassification = "Online"); 

Just adding ForEach from here , noting proisos why it is not enabled by default.

If you want to make WhereCreatedBefore better than a simple extension, for example:

 static class PersonExtensions { public static bool WhereCreatedBefore(this Person p, int year, int month, int day) { return p.CreateDate < new DateTime(year,month,day); } } 

which is useful in itself and gives you:

 somePeople.Where(x => x.CreatedBefore(2000,1,1)) .ForEach(x => x.PersonClassification = "Online"); 

Why limit yourself by simply extending linq tools to make your work easier.

If you want to associate several side effects, a simple ForEach change, for example:

 public static IEnumerable<T> Modify<T>( this IEnumerable<T> input, Action<T> action) { foreach (var x in input) { action(x); yield return x; } } 

gives you:

 somePeople.Where(x => x.CreatedBefore(2000,1,1)) .Modify(x => x.PersonClassification = "Online"); .Modify(x => x.LastModifiedBy = Environment.UserName); 

Or if you use the built-in part of the language:

 (from p in somePeople where p.CreatedBefore(2000,1,1)) select p) .Modify(p => p.PersonClassification = "Online"); .Modify(p => p.LastModifiedBy = Environment.UserName); 

IF you really * wanted you to write a ClassifyAs extension, for example:

 public static IEnumerable<Person> ClassifyAs( this IEnumerable<Person> input, string classification) { foreach (var p in input) { p. PersonClassification = classification; yield return p; } } 

will provide you the original:

 (from p in input where p.CreatedBefore(2000,1,1)) select p).ClassifyAs("Online"); 

This is one liner! without any bizarre structures or type hierarchies, just some useful extension methods. Linq is usually well designed, well implemented, ubiquitous, and well integrated in C #. Repeated execution of parts of the request would be stupid and wasteful that you want to add a side effect to it that causes operations. This is normal (you have mutable objects, so this is unlikely to cause a problem) just add these operations. Just forcing them to continue to contribute, your code will work in style freely.

+2
source

I thought; Its only pseudo code, but does it help?

 public interface IPerson { string PersonClassification { get; set; } DateTime CreateDate { get; set; } } public class Person : IPerson { public string PersonClassification { get; set; } public DateTime CreateDate { get; set; } } public class TransformerBase<T> where T : IPerson { T Person { get; set; } T Transform(Func<T, PersonClassification> transformer) { return transformer(person); } } public class OfflinePersonToOnlineTransformation : TransformerBase<Person> { public OfflinePersonToOnlineTransformation() { Transform(x => x.PersonClassification) .WhenCreatedBefore("1/1/2000") .ClassifyAs("Online"); } } public static class Extensions { public static T WhenCreatedBefore<T>(this T person, string date) where T : IPerson{ if(person == null || person.CreateDate > DateTime.Parse(date)) return null return person; } public static T Classify<T>(this T person, string classification)where T : IPerson{ if(person != null) person.PersonClassification = classification; return person; } } 
0
source

This can help take a step back and write a simple, free interface. You do not need generics or several classes to implement them. The main advantage of a smooth interface is its easy-to-read code. This is achieved by returning it from methods to advance the chain of methods. Here is a basic example. I would start here and return to the desired result.

  public partial class Form1 : Form { public Form1() { InitializeComponent(); } class Calculator { List<int> values = new List<int>(); public Calculator Add(int value) { values.Add(value); return this; } public int Count() { return values.Count; } public int Sum() { return values.Sum(); } } private void Form1_Load(object sender, EventArgs e) { //returns 3 int sum = new Calculator() .Add(1) .Add(2) .Sum(); } } 
-1
source

All Articles