我想type::base用一些常用的功能和流畅的接口构建一个基类(抽象)类(让我们称它),我面临的问题是所有这些方法的返回类型
class base {
public:
base();
virtual ~base();
base& with_foo();
base& with_bar();
protected:
// whatever...
};
Run Code Online (Sandbox Code Playgroud)
现在我可以制作子类型,例如:
class my_type : public base {
public:
myType();
// more methods...
};
Run Code Online (Sandbox Code Playgroud)
使用这样的子类型时出现问题:
my_type build_my_type()
{
return my_type().with_foo().with_bar();
}
Run Code Online (Sandbox Code Playgroud)
这将无法编译,因为我们正在返回base而不是my_type.
我知道我可以:
my_type build_my_type()
{
my_type ret;
ret.with_foo().with_bar();
return ret;
}
Run Code Online (Sandbox Code Playgroud)
但我在想如何实现它,我没有找到任何有效的想法,一些建议?
现在有许多Fluent实现可以与Lambdas一起完成非常整洁的工作.我想把我的大脑包裹起来,这样我就可以开始创造一些这样的东西,但我还没有找到一个我的大脑能够理解的解释.
考虑这个简单的Person Validator示例
public class PersonValidator : IValidator<Person>
{
public PersonValidator()
{
AddRule(p => p.FirstName).CannotBeNull().CannotBeBlank();
AddRule(p => p.LastName).CannotBeNull().CannotBeBlank();
}
public List<ValidationResult> Validate(Person p)
{
// pseudo...
apply all rules specified in constructor, return results
}
}
Run Code Online (Sandbox Code Playgroud)
我已经成功地使用我的Validator上的方法来完成所有这些工作的一部分......
public ValidationResult<T,TProp> AddRule<T,TProp>(Func<T,TProp> property)
{
... not sure what to do here. This method gives me the ability to use the lambda
... for specifying which properties i want to validate
}
Run Code Online (Sandbox Code Playgroud)
然后,我可以创建扩展IValidator的Extension方法,以实现CannotBeNull和CannotBeEmpty的目的.
所以我似乎有问题的上半部分和后半部分,但我不确定如何将它们组合在一起.
寻找有意义的解释...我想"得到它".:)
我们使用构建器模式生成测试数据.这些域对象之间存在关系.我们的功能测试要求保留这些对象.
想想这个模型:
域模型http://i34.tinypic.com/21mg1gn.png
如果我想要一个普通的CI实例 aNew().c().build()
如果我希望它坚持我做 aNew().c().saveIn(session)
如果我想要一个具有已知BI的C实例 aNew().c().with(b).build()
嗯,你明白了.我的问题是,如果我想坚持一个C,它应该坚持它的B吗?或者它应该在手前坚持下去?如果我想要一个合理的默认B呢?如果我想坚持D怎么样?它应该坚持A,B,C吗?
当然,真实的系统要复杂得多(有时带有循环引用).我正在寻找持久复杂测试数据的最佳实践.
编辑:看起来我遇到了语言障碍,我的母语不是英语,所以我很抱歉默默无闻.以下是更多信息:
PS.请不要犹豫,询问更多信息,因为我一直在努力寻找可能的最佳实践.我最接近的是:
这样可行,但我的蜘蛛感觉刺痛,我认为我做错了,因为测试代码会涉及逻辑,如果没有测试,处理起来会非常复杂.
编辑2:我会尽力让自己更清楚.当我编写/运行我的单元和一些集成测试时我没有问题,因为测试数据没有持久化,它存在于内存中.
但是当我试图坚持我的测试数据时,如果没有它的关系,hibernate将不会让我保存一个实体.
我怎样才能克服这个问题?
我正在使用.NET 3.5.我们有一些复杂的第三方类,它们是自动生成的,不受我的控制,但我们必须将它们用于测试目的.我看到我的团队在我们的测试代码中进行了很多深度嵌套的属性获取/设置,而且它变得非常麻烦.
为了解决这个问题,我想建立一个流畅的界面来设置分层树中各种对象的属性.这个第三方库中有大量属性和类,手动映射所有内容太繁琐了.
我最初的想法是只使用对象初始化器.Red,, Blue和Green是属性,并且Mix()是一种方法,将第四个属性设置为Color具有该混合颜色的最接近的RGB安全颜色.涂料在使用Stir()前必须均匀化.
Bucket b = new Bucket() {
Paint = new Paint() {
Red = 0.4;
Blue = 0.2;
Green = 0.1;
}
};
Run Code Online (Sandbox Code Playgroud)
这有助于初始化Paint,但我需要链接Mix()和其他方法.下一次尝试:
Create<Bucket>(Create<Paint>()
.SetRed(0.4)
.SetBlue(0.2)
.SetGreen(0.1)
.Mix().Stir()
)
Run Code Online (Sandbox Code Playgroud)
但这不能很好地扩展,因为我必须为我想要设置的每个属性定义一个方法,并且所有类中都有数百个不同的属性.另外,C#没有办法在C#4之前动态定义方法,所以我认为我不能以某种方式自动挂钩.
第三次尝试:
Create<Bucket>(Create<Paint>().Set(p => {
p.Red = 0.4;
p.Blue = 0.2;
p.Green = 0.1;
}).Mix().Stir()
)
Run Code Online (Sandbox Code Playgroud)
这看起来并不太糟糕,似乎它是可行的.这是一种可行的方法吗?是否可以编写一种Set以这种方式工作的方法?或者我应该采取其他策略?
我有一个PermissionsJava类,方法流畅,如下所示:
somePermissions.setRead(true).setWrite(false).setExecute(true)
Run Code Online (Sandbox Code Playgroud)
问题是,我是否应该命名这些方法set{Property}或仅命名{property}.后者看起来像这样:
somePermissions.read(true).write(false).execute(true)
Run Code Online (Sandbox Code Playgroud)
如果我单独看这些方法,我会期望read读取一些东西,但另一方面,它更接近于像Scala那样使用命名参数的意图:
Permission(read=true, write=false, execute=true)
Run Code Online (Sandbox Code Playgroud) 我知道在PHP中链接的好处,但我们可以说有以下情况
$Mail = new MailClass("mail")
->SetFrom("X")
->SetTo("X")
->SetSubject("X")
->AddRecipient("X")
->AddRecipient("X")
->AddRecipient("X")
->AddRecipient("X")
->AddRecipient("X")
->AddRecipient("X")
->Send();
Run Code Online (Sandbox Code Playgroud)
返回和重复使用对象是否存在任何问题,如速度或未遵循最佳实践等问题
如果您是Fluent-Interface的新手:Fluent-Interfaces上的Martin Fowler,也可以很好地阅读此内容
我完全理解,它不具备进行编程这种方式,能够像这样被处理:
$Mail = new MailClass("mail");
$Mail->AddRecipien(
array(/*.....*/)
);
$Mail->SetFrom("X");
$Mail->SetTo("X");
$Mail->SetSubject("X");
$Mail->Send();
Run Code Online (Sandbox Code Playgroud)
但是让我说我有一个像这样的对象:
$Order = new Order()
->With(22,'TAL')
->With(38,'HPK')->Skippable()
->With(2,'LGV')
->Priority();
Run Code Online (Sandbox Code Playgroud)
请注意->With(38,'HPK')->Skippable(),这是此类编程的Pro的完美示例
我该怎么做才能说InvokeMethod可以调用一个方法,当使用像Repeat这样的特殊选项时,它应该在Repeat之后执行.
我现在的问题是该方法在知道必须被调用100次之前就已经执行了.
class Program
{
static void Main()
{
const bool shouldRun = true;
new MethodExecuter()
.ForAllInvocationsUseCondition(!Context.WannaShutDown)
.InvokeMethod(A.Process).Repeat(100)
.When(shouldRun).ThenInvokeMethod(B.Process).Repeat(10)
.ForAllInvocationsUseCondition(Context.WannaShutDown)
.When(shouldRun).ThenInvokeMethod(C.Process);
}
}
Run Code Online (Sandbox Code Playgroud)
MethodExpression的
public class MethodExpression
{
private bool _isTrue = true;
private readonly MethodExecuter _methodExecuter;
public MethodExpression(bool isTrue, MethodExecuter methodExecuter)
{
_isTrue = isTrue;
_methodExecuter = methodExecuter;
}
public MethodExecuter ThenInvokeMethod(Action action)
{
if (_isTrue)
{
action.Invoke();
_isTrue = false;
}
return _methodExecuter;
}
}
Run Code Online (Sandbox Code Playgroud)
MethodExecuter
public class MethodExecuter
{
private bool …Run Code Online (Sandbox Code Playgroud) 我在ASP.NET核心2.0类库中使用FluentEmail,它将发送电子邮件通知.
下面是我到目前为止尝试过的示例代码:
using FluentEmail.Core;
using FluentEmail.Razor;
using FluentEmail.Smtp;
using System;
using System.IO;
using System.Net.Mail;
using System.Net.Mime;
namespace FluentEmail
{
public class EmailNotification : IEmailNotification
{
public bool SendEmailNotification()
{
try
{
//Setup Default sender befault sending the email.
SmtpClient smtpClient = new SmtpClient
{
Host = "smtp.office365.com",
Port = 587,
EnableSsl = true,
Credentials = new System.Net.NetworkCredential("username", "Password")
};
Email.DefaultSender = new SmtpSender(smtpClient);
Email.DefaultRenderer = new RazorRenderer();
string imagePath = @"C:\Users\pratik.soni\Downloads\FluentLogo.png";
Stream stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read); …Run Code Online (Sandbox Code Playgroud) 我有一个Customer实体,它引用了一组地址.这里的复杂性是我希望能够将特定地址识别为默认地址.
如果可能的话,我想在Customer表中保存默认地址的FK.这似乎比在地址表中有一列来识别默认值更优雅.
在定义这种关系方面,我在使用流畅的API方面遇到了困难.当我运行以下代码时,我得到一个异常,其中说: "保存未公开其关系的外键属性的实体时发生错误.EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源通过在实体类型中公开外键属性,可以更容易地在保存时处理异常.有关详细信息,请参阅InnerException."无法确定依赖操作的有效排序.由于外键约束,模型要求或存储生成的值,可能存在依赖关系."
我创建了一个控制台应用程序来显示确切的问题.在这个测试应用程序中,我有一个Customer实体,一个Address和flient api配置.
任何帮助将非常感激:
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
namespace OneToManyWithDefault
{
public class Customer
{
private ICollection<Address> m_Addresses;
public Customer()
{
Addresses = new List<Address>();
}
public int Id { get; set; }
public string CompanyName { get; set; }
public virtual ICollection<Address> Addresses
{
get
{
if (m_Addresses == null)
{
m_Addresses = new List<Address>();
}
return m_Addresses;
}
set
{
m_Addresses = value;
}
}
public Address DefaultAddress { …Run Code Online (Sandbox Code Playgroud) 我想在我的mvc网站上实现流畅的api.我得到了基础知识.所以实现对象库如:
public class UIElement{/*...*/}
public class ButtonBase : UIElement{/*...*/}
public class LinkButton : ButtonBase {/*...*/}
public static class Extensions
{
public static T UIElementMethod<T>(this T element, string title)
where T : UIElement
{
return element;
}
public static T ButtonBaseMethod<T>(this T element, string title)
where T : ButtonBase
{
return element;
}
public static T LinkButtonMethod<T>(this T element, string title)
where T : LinkButton
{
return element;
}
}
Run Code Online (Sandbox Code Playgroud)
但是如何在没有一些flush方法调用的剃刀视图中使用它.
@Html.UIproject().LinkButton()
.UIElementMethod("asd")
.ButtonBaseMethod("asd")
.LinkButtonMethod("asd")
Run Code Online (Sandbox Code Playgroud)
但它返回类的名称.我试图为MvcHtmlString创建一个隐式运算符,但它没有被调用.任何想法如何实现这一点.如何知道它是链和链.我喜欢 Kendo UI的工作方式.
谢谢,
Péter
fluent-interface ×10
c# ×3
.net-3.5 ×1
asp.net-mvc ×1
c++ ×1
chaining ×1
email ×1
entity ×1
html-email ×1
inheritance ×1
java ×1
lambda ×1
naming ×1
object ×1
persistence ×1
php ×1
razor ×1
scala ×1
test-data ×1
testing ×1
xml ×1