Ну вот. Через рефлекшены посмотреть, есть ли у объекта a метод add(b.Type), если есть - то получить экземпляр метода и вызвать его с параметрами a и b.
В Java это вполне легитимная практика, так что и в .NET должно быть нечто подобное.
Любую задачу можно решить введением нового уровня абстрации :) в данном случае это паттерн Прокси. Оберни object новым типов DuckObject и перегрузи у него операторы.
Хотя, если cишарп уже поддерживает темную магию метапрограммирования, то будет совсем хорошо :)
0) а точно дженериков не хватит (с этого надо было начать, anyway)? 1) генерация прокси. См., например, DynamicProxy в CastleProject или LinFu. 2) Извраты с рефлекшеном/expression trees (см. мой недавний облажанный пост =) в качестве демонстрации идеи). Типа Expression> e = (a,b) => a + b; где INum - некий тип, поддерживающий нужные операции (+, -, ...) Потом проходишься по дереву визитором (в MSDN есть статья) и строишь эквивалентное дерево, где INum заменен на нужный тебе тип, а абстрактные операции - на нужные тебе. 3) почему нельзя подключить язык с динамической типизацией? JScript (obsolete, но все же), Boo, IronPython, IronRuby?
0) дженерики же тоже компайл-тайм, как ты в рантайме их прикрутишь? возможно, через рефлекшен, но через рефлекшен есть более очевидные пути, которых как раз хочется избежать (ну то есть так уже реализовано почти, ищу альтернативы) 1) прокси да, уже прикручиваю... сделал WeakTypedObject прокси -- типа, объект, который оборачивает object, перегружает все мыслимые операторы и бросает эксепшен, если обернутый тип не поддерживает -- но есть свои минусы, всё равно в итоге всё сводится к преобразованию внутреннего object в разные встроенные типы 2) да, что-то такое и реализовано... дай точную ссылку на пост, а то я не помню когда это было :-) 3) вероятно, сложности с поддержкой кода потом :-)
1) А ты уверен, что тебе таки реально нужна динамическая типизация, а не какая-то иная возможность построения обобщённых алгоритмов? Может, их проще описать просто в более-менее отвлеченном от конкретных типов варианте, возложив специфику вычисления тех или иных значений на стратегии, а конкретные типы все равно подставятся уже в рантайме? 2) http://georgeelder.blogspot.com/2008/08/c-expression-trees.html - показано, как их строить ручками, хотя там пример другой. Однако можно возложить на компилятор. про модификацию - см. тут (или ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_fxadvance/html/2c9001bb-6422-4a85-80c1-c587df45d9ab.htm в хелпе к VS 2008). В твоем случае нужно будет заменить типы аргументов, а также MethodInfo для методов-операторов. В общем, гимор тот же, но есть возможность возложить синтаксис на компилятор и проверить ошибки все разом, в момент компиляции дерева выражения, а не при обращении к каждому конкретному методу
( ... )
А если сделать кодогенератор, который будет для всех стандартных типов, имеющих нужную операцию, генерировать метод. Конечно, это не совсем Runtime, но, кажется, можно и динамически генерировать код
Кажется Юра делал какой-то код и кодогенератором, и динамически. Его поспрошай. Мне это тоже интересно, но слышал про эти два подхода я именно от него.
Comments 22
(если правельно понял вопрос)
Reply
Reply
{
try
{
return ""+(int.Parse(arg1)+int.Parse(arg2));
}
catch (DunnoWhichException e) {}
try
{
return ""+(float.Parse(arg1)+float.Parse(arg2));
}
catch (DunnoWhichException e) {}
return arg1+arg2;
}
Reply
Hope that helps.
Reply
но к операции сложения такое, по-моему, применить нельзя...
Reply
Reply
Reply
Reply
object a, object b
Хочу просто вернуть сумму, когда это возможно
return a+b;
А в шарпе получится, что надо как-то гиморно вроде:
typea = a.Type;
typeb = b.Type;
if(typea == typeb){
if(typea == typeof(int)){
return (int)a + (int)b;
}
if(typea == typeof(double)){
return (double)a + (double)b;
}
...
}
Reply
В Java это вполне легитимная практика, так что и в .NET должно быть нечто подобное.
Reply
Хотя, если cишарп уже поддерживает темную магию метапрограммирования, то будет совсем хорошо :)
Reply
1) генерация прокси. См., например, DynamicProxy в CastleProject или LinFu.
2) Извраты с рефлекшеном/expression trees (см. мой недавний облажанный пост =) в качестве демонстрации идеи).
Типа
Expression> e = (a,b) => a + b;
где INum - некий тип, поддерживающий нужные операции (+, -, ...)
Потом проходишься по дереву визитором (в MSDN есть статья) и строишь эквивалентное дерево, где INum заменен на нужный тебе тип, а абстрактные операции - на нужные тебе.
3) почему нельзя подключить язык с динамической типизацией? JScript (obsolete, но все же), Boo, IronPython, IronRuby?
Это то, что на ум приходит.
Reply
1) прокси да, уже прикручиваю... сделал WeakTypedObject прокси -- типа, объект, который оборачивает object, перегружает все мыслимые операторы и бросает эксепшен, если обернутый тип не поддерживает -- но есть свои минусы, всё равно в итоге всё сводится к преобразованию внутреннего object в разные встроенные типы
2) да, что-то такое и реализовано... дай точную ссылку на пост, а то я не помню когда это было :-)
3) вероятно, сложности с поддержкой кода потом :-)
Reply
2) http://georgeelder.blogspot.com/2008/08/c-expression-trees.html - показано, как их строить ручками, хотя там пример другой. Однако можно возложить на компилятор.
про модификацию - см. тут (или ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_fxadvance/html/2c9001bb-6422-4a85-80c1-c587df45d9ab.htm в хелпе к VS 2008). В твоем случае нужно будет заменить типы аргументов, а также MethodInfo для методов-операторов. В общем, гимор тот же, но есть возможность возложить синтаксис на компилятор и проверить ошибки все разом, в момент компиляции дерева выражения, а не при обращении к каждому конкретному методу ( ... )
Reply
Reply
Reply
Reply
Reply
Leave a comment