我希望能够创建“转换”类,它接受给定对象,对其执行一系列转换(即更改属性值)并跟踪执行的转换。执行的转换将根据提供的对象的属性而有所不同。
我希望能够使用流畅的样式界面在给定的转换类中应用转换规则(有限和commin)。
在较高的层面上,我知道我可能会有一个ITransformer,一个ITransformationRule和ITransformationResult,还有一些其他对象来实现这一目标。
在创建Transformation类时,我希望代码如何工作......
public OfflinePersonToOnlineTransformation : TransformerBase<Person>
{
public OfflinePersonToOnlineTransformation()
{
Transform(x => x.PersonClassification)
.WhenCreatedBefore("1/1/2000")
.ClassifyAs("Online");
}
}
据我所知,我的TransformerBase需要实现采用Func或Expression的“Transform”方法,并且我理解它需要保留ITransformationRules的集合。我也理解我可能会使用Extension方法来处理“WhenCreatedBefore”和“ClassifyAs”方法。
麻烦的是,我无法弄清楚如何使一切顺利。我查看了Fluent Validation .NET的源代码,因为它以这种方式验证,但复杂性让我感到害怕。我正在寻找一个涵盖这个的教程,或者是一个以非常简单的方式拼写它的人。
提前致谢。
答案 0 :(得分:2)
当linq为您完成大部分工作时,不太确定为什么要进行所有这些工作:
IEnumerable<Person> somePeople; // from wherever
somePeople.Where(x => x.CreateDate < new DateTime(2000,1,1))
.ForEach(x => x.PersonClassification = "Online");
只需添加来自here的ForEach,并注明默认情况下未包含的原因。
如果你想使WhereCreatedBefore更好,那么就像这样简单的扩展:
static class PersonExtensions
{
public static bool WhereCreatedBefore(this Person p,
int year, int month, int day)
{
return p.CreateDate < new DateTime(year,month,day);
}
}
这本身就很有用,并为您提供:
somePeople.Where(x => x.CreatedBefore(2000,1,1))
.ForEach(x => x.PersonClassification = "Online");
为什么在简单地扩展工具时限制自己linq让你更轻松。
如果您想链接多个副作用,只需更改ForEach:
public static IEnumerable<T> Modify<T>(
this IEnumerable<T> input, Action<T> action)
{
foreach (var x in input)
{
action(x);
yield return x;
}
}
给你:
somePeople.Where(x => x.CreatedBefore(2000,1,1))
.Modify(x => x.PersonClassification = "Online");
.Modify(x => x.LastModifiedBy = Environment.UserName);
或者,如果您使用语言集成部分:
(from p in somePeople where p.CreatedBefore(2000,1,1)) select p)
.Modify(p => p.PersonClassification = "Online");
.Modify(p => p.LastModifiedBy = Environment.UserName);
如果您真的想要,可以像这样写一个ClassifyAs扩展名:
public static IEnumerable<Person> ClassifyAs(
this IEnumerable<Person> input, string classification)
{
foreach (var p in input)
{
p. PersonClassification = classification;
yield return p;
}
}
给你原件:
(from p in input where p.CreatedBefore(2000,1,1)) select p).ClassifyAs("Online");
哪一个是班轮!没有花哨的框架或类型层次结构,只需要一些有用的扩展方法。 Linq通常设计良好,实施良好,无处不在并且很好地集成到c#中。重新实现它的查询部分将是愚蠢和浪费,你想要的是添加副作用导致操作。这很好(你有可变对象所以这几乎不会导致问题)只需添加这些操作。只是让它们继续产生输入将使你的代码流畅。
答案 1 :(得分:0)
我有一个想法;它唯一的伪代码,但这有帮助吗?
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;
}
}
答案 2 :(得分:-1)
退一步并首先编写一个简单的流畅界面可能会有所帮助。您不需要泛型或多个类来实现它。流畅的界面模式的主要好处是易于阅读代码。它是通过从方法返回来促进方法链接来完成的。这是一个基本的例子。我会从这里开始,向后研究你想要的结果。
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();
}
}