2016-12-29 2 views
4

У меня есть класс, который содержит несколько методов, например .:C# ограничить методы к другим методам

class mySqlTool{ 

    private string _values, _table, _condition, _result; 

    public mySqlTool Select(string values = null){ 
     //this is REQUIRED 
     _values = string.Format("select {0} ", values); 
     return this; 
    } 

    public mySqlTool Update(string table){ 
     //this is REQUIRED 
     _table = table; 
     return this; 
    } 

    public mySqlTool Set(string name, String value){ 
     //this is REQUIRED 
     //handle name and value 
     return this; 
    } 

    public mySqlTool From(string table = null){ 
     //this is REQUIRED 
     _table = table; 
     return this; 
    } 
    public mySqlTool Where(string condition = null){ 
     //this is OPTIONAL 
     _condition = condition; 
     return this; 
    } 
    public string Execute(){ 
     //this is REQUIRED 
     //this is samplecode, of course here is checked if its select or update 
     //but to keep it short i erased it 

     statement = string.Format("{0} {1}", _values, _table); 

     if (!string.IsNullOrEmpty(_condition)) 
     { 
      statement += string.Format(" where {0}", _condition); 
     } 
     //do some with statemen and fill result 
     return _result; 
    } 
} 

Я теперь использую это в этом цепном способе:

MySqlTool t = new MySqlTool(); 
string result = t.Select("a,b,c").From("x").Where("foo=bar").Execute(); 

My VS обеспечивает меня доступные методы когда я ударил DOT (.).

Моя проблема, я хочу, чтобы использовать дение некоторых методов, прежде чем другие методы были использованы, например:

MySqlTool.Where().Select().From().Execute(); 

В этом случае .C() не должен быть отозван Befor .A() называется. Таким образом, чтобы уточнить, Что позволено и Что не так, вот небольшой список

//Allowed 
t.Select().From().Execute(); 
t.Select().From().Where().Execute(); 
t.Update().Set().Set().Set().Where().Where().Where().Execute(); 

//not Allowed 
t.Select().Where().Execute(); 
t.Select().Select().Select().From().Execute(); 
t.From()... 
t.Where()... 
t.Execute().... 

Я читал некоторые об интерфейсах, а также о состоянии, но я не уверен, если это то, что поиск им для.

Так что мой вопрос:

Это то, что я хочу, даже возможно?

Если да, то как называется этот метод?

+0

Состояние машины для .net? – ilansch

+2

Этот метод называется «беглый intreface». – Evk

+1

Не во время компиляции, во время выполнения вы можете иметь состояние. Просто ... Не надо. – Thomas

ответ

10

Общее описание - см конец для конкретных замечаний

Это то, что я хочу, даже возможно?

Не в пределах того же класса, нет. Как компилятор узнает, что вы уже назвали? (Представьте, что у вас был метод с параметром типа Test - какие методы должны быть доступны для вызова?) Система типа решает, что действительно, а что нет - поэтому, если существуют разные наборы действительных операций, которые предлагают разные типы.

Что вы может do имеют разные типы, представляющие различные состояния, в которые будут включены только соответствующие методы для перехода состояния. Таким образом, вы могли бы иметь что-то вроде этого:

class Test0 // Initial state 
{ 
    public Test1 A() { ... } 
} 

class Test1 // After calling A 
{ 
    public Test2 B() { ... } 
} 

class Test2 // After calling B 
{ 
    // This returns the same type, so you can call B multiple times 
    public Test2 B() { ... } 

    // This returns the same type, so you can call C multiple times 
    public Test2 C() { ... } 

    public string DoSomething() { ... } 
} 

Затем вы можете использовать:

Test0 t = new Test0(); 
string x1 = t.A().B().DoSome(); 
string x2 = t.A().B().C().DoSome(); 
string x3 = t.A().B().B().B().C().C().C().DoSome(); 

... но недействительные случаи не компилировать.

Это работает, но это довольно уродливо. Не зная, для чего предназначены методы, трудно предложить что-либо еще, но во многих случаях один метод с необязательными параметрами может быть лучше или, возможно, шаблон-строитель.

Альтернативой является использование одного класса и проверка вызовов во время выполнения, а не во время компиляции. Это менее полезно при кодировании, но позволяет избежать огромного беспорядка типов.

Еще одна альтернатива - иметь один класс - и создать один экземпляр - но использовать интерфейсы для представления состояния.Ваш класс будет реализовывать все интерфейсы, так что он может еще раз вернуться this:

interface IStart 
{ 
    IMiddle A(); 
} 

interface IMiddle 
{ 
    IFinal B(); 
} 

interface IFinal 
{ 
    IFinal B(); 
    IFinal C(); 
    string DoSomething(); 
} 

class Test : IStart, IMiddle, IFinal 
{ 
    public IMiddle A(string x = null) { return this; } 
    public IFinal B(string x = null) { return this; } 
    public IFinal C(string x = null) { return this; } 
    public string DoSomethign { ... } 
} 

Тогда вы должны:

IStart t = new Test(); 
string x1 = t.A().B().DoSome(); 
string x2 = t.A().B().C().DoSome(); 
string x3 = t.A().B().B().B().C().C().C().DoSome(); 

Но это чувствует себя довольно неправильно для меня. Я ожидал бы, что методы , B и C будут эффективно изменять состояние в некотором роде - поэтому отдельные типы будут указывать, какое состояние доступно. В первом примере Test0 определенно не имеют состояние, представленное A вызова, но Test1делает ... и Test2 инстанции состояния обеспечивается A и B, и, возможно, C.

Конкретный пример

Для конкретного примера, приведенного, я бы, вероятно, просто сделать конструктор обрабатывать необходимую информацию (имя таблицы) и потребительских свойств/шагового для отдыха. Я бы, наверное, выделить команду запроса из обновлений:

SqlQuery query = new SqlQuery("table") 
{ 
    Columns = { "a", "b", "c" }, 
    Where = { "foo=bar" } // Not sure how you're parameterizing these 
}; 

И:

SqlUpdate update = new SqlUpdate("table") 
{ 
    // Which columns to update with which values 
    ["a"] = 10, 
    ["b"] = 20, 
    Where = { "foo=bar" } // Not sure how you're parameterizing these 
}; 

В каждом случае бы быть Execute метод, возвращающий соответствующие результаты.

+0

это все еще цепной? – Dwza

+0

@ Dwza: Вы попробовали? Почему бы это не быть цепным? –

+0

Я просто прочитал его и попросил ... использовать его таким образом займет некоторое время, чтобы переделать мой код ^^ Я просто предоставил образец. Мой источник я намного больше. Я буду создавать образец программы для проверки этого. Я вернусь: D – Dwza

Смежные вопросы