vir
Зарегистрирован: 17.05.2007 Сообщения: 24
|
Добавлено: Пт Авг 03 2007 11:43 Заголовок сообщения: Embedded DSL в C# |
|
|
Здравствуйте,
Подскажите пожалуйста, как реализовать описанную ниже схему
я определил такие вот классы:
Код: |
public interface SQLExp
{
public string getRendering ();
}
public interface SQLExpString : SQLExp
{
}
public interface SQLExpNumber : SQLExp
{
}
public interface SQLExpDateTime : SQLExp
{
}
public interface SQLExpBool : SQLExp
{
}
public class SQLStringLiteral : SQLExpString
{
string str;
public SQLStringLiteral (string s)
{
this.str = s;
}
public string getRendering ()
{
return "'"
+ str.Replace ("'", "\\'")
.Replace ("\n", "\\n")
.Replace ("\r", "\\r")
+ "'";
}
}
public class SQLNumberLiteral : SQLExpNumber
{
...
}
public class SQLDateTimeLiteral : SQLExpDateTime
{
...
}
abstract class SQLBinOp : SQLExp
{
SQLExp a;
SQLExp b;
public SQLBinOp (SQLExp a, SQLExp b)
{
this.a = a;
this.b = b;
}
protected abstract string getOpString ();
public string getRendering ()
{
return "(" + a.getRendering () + " " + getOpString () + " " + a.getRendering () + ")";
}
}
public class SQLAddNumber : SQLBinOp, SQLExpNumber
{
public SQLAddNumber (SQLExpNumber a, SQLExpNumber b)
: base (a, b)
{
}
protected override string getOpString ()
{
return "+";
}
}
|
и так много операций
для разных типов
а теперь вопрос, я могу как-нить определить
Код: |
public static SQLExpNumber operator + (SQLExpNumber a, SQLExpNumber b)
{
return new SQLAddNumber (a, b);
}
|
???
по идее надо SQLExpNumber превратить в класс из интерфейса, но тогда всё сломается... возможно ли это?
Цитата: |
Piglet (11:29:49 3/08/2007)
не втуплю... зачем преобразовывать в класс?
|
в каком классе тогда написать
Код: |
public static SQLExpNumber operator + (SQLExpNumber a, SQLExpNumber b)
{
return new SQLAddNumber (a, b);
}
|
?
Цитата: |
Piglet (11:31:22 3/08/2007)
а
|
вот и я в шоке
Цитата: |
Piglet (11:47:16 3/08/2007)
а можно ли добавить в определение SQLExpNumber декларацию оператора +?
а потом класс реализующий SQLExpNumber его переопределит
не?
|
Цитата: |
vir (12:11:06 3/08/2007)
error CS0567: Interfaces cannot contain operators
|
Цитата: |
Piglet (12:11:45 3/08/2007)
тогда реализуй метод add )))
давжопуоператоры
|
ну прикольно было бы писать, что-то вроде
Код: |
QuerySelect q = new QuerySelect ()
.addSource("table1")
.addFilter(SQL.Attr.Bool["name"] == SQL.Lit ("Вася") && SQL.Attr.DateTime["time"] > SQL.Lit (DateTime.Now()))
|
или как-то так
Цитата: |
Piglet (12:16:29 3/08/2007)
SQL.Attr.Bool["name"] == SQL.Lit ("Вася") - точно Bool?
|
не бул, и идея, в том что тайп чекер СиШарпа тебе об этом скажет
Цитата: |
Piglet (12:18:20 3/08/2007)
не понял.. то есть здесь компилятор должен ругнуться
SQL.Attr.Bool["name"] == SQL.Lit ("Вася")
?
|
да
SQL.Lit ("Вася") :: SQLExpString
SQL.Attr.Bool["name"] :: SQLExpBool
просто тогда вместо:
Код: |
SQL.Attr.Bool["name"] == SQL.Lit ("Вася") && SQL.Attr.DateTime["time"] > SQL.Lit (DateTime.Now())
|
придётся писать:
Код: |
SQL.And (SQL.Eq (SQL.Attr.Bool["name"], SQL.Lit ("Вася")), SQL.Gt (SQL.Attr.DateTime["time"], SQL.Lit (DateTime.Now()))
|
я просто написал вот такую штуку:
Код: |
QueryInsert qi = new QueryInsert (protocolTable);
qi[cardIdCol] = SQL.Lit (cardId);
qi[resolIdCol] = SQL.Lit (resolId);
qi[senderIdCol] = SQL.Lit (realUserId);
qi[receiverIdCol] = SQL.Lit (receiverId);
qi[opCodeCol] = SQL.Lit (opCode);
qi[timeCol] = SQL.Lit (DateTime.Now);
if (prevOpCode.HasValue)
qi[prevRecordIdCol] = SQL.Lit (prevOpCode.Value);
return qi.RunIdentity ();
|
и подумал, что можно написть втроенный DSL и для других запросов |
|