见以下代码:
new ConditionCreator()
.Add()
.Or()
.Add()
.And()
.Add()
我想为此创建一个Fluent界面 但是我需要, 在Add()方法开发人员之后看到只有Or()或And() 和 在其中一个之后,请参阅Only Add()方法。
所以没有人可以编写如下代码:
new ConditionCreator()
.Add()
.Add()
.Add()
.Or()
.And()
.Add()
.And()
.And()
我想对某些方法有限制可以接受特殊方法等。 我可以在一个类中编写所有方法并为每个方法返回这个方法,但这不合适!!!
请指导我如何编写Advanced Fluent Interface类。
答案 0 :(得分:4)
要限制事物,你需要创建并返回一个(可能是几个)" builder"可以执行特殊操作的对象,保留对主类的引用。
public class ConditionCreator
{
public ConditionCreator() { ... }
public SubConditionCreator Add() { ...; return new SubConditionCreator(this); }
internal ConditionCreator OnAdd() { ...; return this; };
internal ConditionCreator OnOr() { ...; return this; };
}
public class SubConditionCreator
{
private ConditionCreator _creator;
internal SubConditionCreator(ConditionCreator c) { _creator = c; }
public ConditionCreator And() { return _creator.OnAdd(); }
public ConditionCreator Or() { return _creator.OnOr(); }
}
使用内部访问来限制使用。
为避免产生垃圾,请在主类中存储SubConditionCreator参考
答案 1 :(得分:2)
我不知道解决这个问题的真正方法。也许T4模板可能有所帮助,但到目前为止,我总是不得不建立决策树,每个节点都有一个显式接口。例如;假设你的决策树是一个无限循环,然后(相应地实现):
interface IStart<T>
{
IAndOr Add();
T End();
}
interface IAndOr<T>
{
IStart<T> And();
IStart<T> Or();
}
如果你想要一个有限的循环,那就很难了;说零到两个添加:
interface IStart<T> : IFinish<T>
{
IAndOrFirst<T> Add();
}
interface IAndOrFirst<T>
{
ISecond<T> And();
ISecond<T> Or();
}
interface ISecond<T> : IFinish<T>
{
IAndOrSecond<T> Add();
}
interface IAndOrSecond <T>
{
IFinish<T> And();
IFinish<T> Or();
}
interface IFinish<T>
{
T End();
}
您可以(明确地)在充当状态机的单个类中实现这些:
class ConditionCreator <T> : IStart<T>, IFinish<T>, IAndOrFirst<T>, IAndOrSecond<T> {...}
您要为this
Add()
And()
返回Or()
,并维护这些状态更改和订单。
我希望能够以更好的方式手动写出每个节点来回答这个问题。
答案 2 :(得分:0)
考虑返回仅包含And()
和Or()
的界面。例如:
public class ConditionCreator : IFluentAndOr
{
public IFluentAndOr And() { ... }
public IFluentAndOr Or() { ... }
}
public interface IFluentAndOr
{
IFluentAndOr And();
IFluentAndOr Or();
}
答案 3 :(得分:0)
public class DoEqual
{
}
public interface ICanAddWhereValue
{
ICanAddWhereOrRun IsEqualTo(object value);
ICanAddWhereOrRun IsNotEqualTo(object value);
IBothEqual BothEqual ( object value );
}
public interface IBothEqual
{
DoEqual Excute();
}
public interface ICanAddWhereOrRun
{
ICanAddWhereValue Where(string columnName);
bool RunNow();
DoEqual Excute();
}
public interface ICanAddCondition
{
ICanAddWhereValue Where(string columnName);
bool AllRows();
}
namespace BuildAFluentInterface
{
public class WhereCondition
{
public enum ComparisonMethod
{
EqualTo,
NotEqualTo
}
public string ColumnName { get; private set; }
public ComparisonMethod Comparator { get; private set; }
public object Value { get; private set; }
public WhereCondition(string columnName, ComparisonMethod comparator, object value)
{
ColumnName = columnName;
Comparator = comparator;
Value = value;
}
}
}
using System.Collections.Generic;
namespace BuildAFluentInterface
{
public class DeleteQueryWithoutGrammar
{
private readonly string _tableName;
private readonly List<WhereCondition> _whereConditions = new List<WhereCondition>();
private string _currentWhereConditionColumn;
// Private constructor, to force object instantiation from the fluent method(s)
private DeleteQueryWithoutGrammar(string tableName)
{
_tableName = tableName;
}
#region Initiating Method(s)
public static DeleteQueryWithoutGrammar DeleteRowsFrom(string tableName)
{
return new DeleteQueryWithoutGrammar(tableName);
}
#endregion
#region Chaining Method(s)
public DeleteQueryWithoutGrammar Where(string columnName)
{
_currentWhereConditionColumn = columnName;
return this;
}
public DeleteQueryWithoutGrammar IsEqualTo(object value)
{
_whereConditions.Add(new WhereCondition(_currentWhereConditionColumn, WhereCondition.ComparisonMethod.EqualTo, value));
return this;
}
public DeleteQueryWithoutGrammar IsNotEqualTo(object value)
{
_whereConditions.Add(new WhereCondition(_currentWhereConditionColumn, WhereCondition.ComparisonMethod.NotEqualTo, value));
return this;
}
#endregion
#region Executing Method(s)
public void AllRows()
{
ExecuteThisQuery();
}
public void RunNow()
{
ExecuteThisQuery();
}
#endregion
private void ExecuteThisQuery()
{
// Code to build and execute the delete query
}
}
}
<br>
In Main Test with
public class myclass
{
private static void Main(string[] args)
{
DoEqual x3 =
DeleteQueryWithGrammar.DeleteRowsFrom("Account")
.Where("Admin")
.IsNotEqualTo("Admin")
.Where("Admin")
.BothEqual("X")
.Excute();
}
}
答案 4 :(得分:0)
这似乎有效。
public class ConditionCreator
{
private Decision decision;
public ConditionCreator() { decision = new Decision(this); }
public Decision Add() { return decision; }
public class Decision
{
private ConditionCreator creator;
public Decision(ConditionCreator creator) { this.creator = creator; }
public ConditionCreator And() { return creator; }
public ConditionCreator Or() { return creator; }
public Condition Create() { return new Condition(); }
}
}
现在,当你拨打电话时,你现在被限制在这样的模式中:
var condition = new ConditionCreator()
.Add()
.Or()
.Add()
.And()
.Add()
.Create();