В COM'е была классная штука — идентификация интерфейсов по GUID'у. Две совершенно разных библиотеки, не имеющих явных ссылок друг на друга, могли быть клиентом и сервером, потому, что в обеих был описан один и тот же интерфейс с одним и тем же идентификатором. На C# с этим облом — надо референсить третью библиотеку, которая нужна только как хранилище интерфейсов. Является ли это свойством языка, или всего дотнета? Поскольку, если только языка, то было бы здорово иметь хотя бы в одном нормальном языке (N) возможность избежать манки-форсед ограничения. Необходимость таскать сборки с интерфейсами зачастую просто убивает.
Здравствуйте, Аноним, Вы писали:
А>Является ли это свойством языка, или всего дотнета?
В том-то и фича — эта третья библиотека позволят гарантировать то, что клиент и сервер работают с одинаковым интерфейсом.
/* иЗвиНите зА неРовнЫй поЧерК */
Re: Импорт
От:
Аноним
Дата:
20.02.11 08:25
Оценка:
Здравствуйте, Аноним, Вы писали:
А>не имеющих явных ссылок друг на друга
COM уже порядком забыл, но общие заголовочные файлы-то надо было иметь и в составе клиента и в составе сервера.
Чем это не явные ссылки?
А>Необходимость таскать сборки с интерфейсами зачастую просто убивает
Чем это? Они же всегда заведомо маленькие.
Если напрягает количество сборок, то можно делать merge сборок в одну или несколько большего размера.
И, кстати, .NET поддерживает заведомо большую часть инфраструктуры COM.
Re[2]: Импорт
От:
Аноним
Дата:
20.02.11 16:29
Оценка:
Здравствуйте, Аноним, Вы писали:
А>>не имеющих явных ссылок друг на друга А>COM уже порядком забыл, но общие заголовочные файлы-то надо было иметь и в составе клиента и в составе сервера. А>Чем это не явные ссылки?
Забыли. Нет, не надо было. Можно было независимо (на клиенте и сервере) описать интерфейс, привести указатель к этому интерфейсу и юзать. Надо было только знать GUID, чтобы было чего query.
А>>Необходимость таскать сборки с интерфейсами зачастую просто убивает А>Чем это? Они же всегда заведомо маленькие. А>Если напрягает количество сборок, то можно делать merge сборок в одну или несколько большего размера.
Тем, что это лишняя сущность. Одно дело сторонам обменяться гуидом, другое дело — целой сборкой, которую потом еще грузить. При работе со всякими SQLCLR или плагинными системами это вылезает постоянно.
А>И, кстати, .NET поддерживает заведомо большую часть инфраструктуры COM.
И?
Re[2]: Импорт
От:
Аноним
Дата:
20.02.11 16:39
Оценка:
Здравствуйте, hardcase, Вы писали:
А>>Является ли это свойством языка, или всего дотнета? H>В том-то и фича — эта третья библиотека позволят гарантировать то, что клиент и сервер работают с одинаковым интерфейсом.
А знаете в чем фича отсутствия макросов в шарпе? Это позволяет гарантировать, что вообще все программисты будут работать с одинаковым набором синтаксических элементов.
Я только обрадовался, что залудили язык для нормальных пацанов, с макросами и всеми делами, и такой... манки-дривен аргумент.
Так это свойство платформы или языка? Когда вы приводите object к (IFoo) из другой сборки, можно эту работу в принципе выполнить не загружая ее?
Здравствуйте, Аноним, Вы писали:
А>В COM'е была классная штука — идентификация интерфейсов по GUID'у. Две совершенно разных библиотеки, не имеющих явных ссылок друг на друга, могли быть клиентом и сервером, потому, что в обеих был описан один и тот же интерфейс с одним и тем же идентификатором. На C# с этим облом — надо референсить третью библиотеку, которая нужна только как хранилище интерфейсов. Является ли это свойством языка, или всего дотнета? Поскольку, если только языка, то было бы здорово иметь хотя бы в одном нормальном языке (N) возможность избежать манки-форсед ограничения. Необходимость таскать сборки с интерфейсами зачастую просто убивает.
Очередной фичреквест на duck typing. Платформа действительно не позволяет эффективно его реализовать? Хорошо бы подумать над этим.
Здравствуйте, Ziaw, Вы писали:
Z>Очередной фичреквест на duck typing. Платформа действительно не позволяет эффективно его реализовать? Хорошо бы подумать над этим.
DLR позволяет. Но я так чувствую, что для начала, надо взять макрос late и внаглую позиционировать его, как "впихнули невпихуемое", т.е. как реализацию динамической типизации безо всяких DLR.
Здравствуйте, hardcase, Вы писали:
H>Это свойство платформы. А>>Когда вы приводите object к (IFoo) из другой сборки, можно эту работу в принципе выполнить не загружая ее? H>Нет Я думаю вам следует изучить принципы .NET, понятия сборок, систему типов.
Это из-за IL-инструкции castclass?
Re[2]: Импорт
От:
Аноним
Дата:
20.02.11 19:24
Оценка:
Здравствуйте, Ziaw, Вы писали:
А>>В COM'е была классная штука — идентификация интерфейсов по GUID'у. Две совершенно разных библиотеки, не имеющих явных ссылок друг на друга, могли быть клиентом и сервером, потому, что в обеих был описан один и тот же интерфейс с одним и тем же идентификатором. На C# с этим облом — надо референсить третью библиотеку, которая нужна только как хранилище интерфейсов. Является ли это свойством языка, или всего дотнета? Поскольку, если только языка, то было бы здорово иметь хотя бы в одном нормальном языке (N) возможность избежать манки-форсед ограничения. Необходимость таскать сборки с интерфейсами зачастую просто убивает.
Z>Очередной фичреквест на duck typing. Платформа действительно не позволяет эффективно его реализовать? Хорошо бы подумать над этим.
Вообще-то, я имел в виду именно приведение интерфейсов. То есть, эффективность 100%. Но если верить hardcase, это невозможно. Что ж, если небольшое снижение производительности — та цена, которую надо заплатить, я лично готов.
Проблема, однако, вот в чем. DT должен поддерживаться на обоих концах. Допустим, есть IDispatch с Invoke(string MethodeName). Он должен входить в FW, чтобы и клиент, и сервер его видели (один дергал, другой реализовывал), пусть даже на клиенте язык позволяет прозрачно превращать вызовы в Invoke. Когда последний раз мне это было надо, я спрашивал на форуме .Net, есть ли какой-то подходящий интерфейс, ответ был — нету (действительно нет?). Как бы вы не реализовали DT, в это все упрется.
Здравствуйте, kochetkov.vladimir, Вы писали:
А>>Является ли это свойством языка, или всего дотнета?
KV>Test.exe(FooLib1 и FooLib2 в референсах отсутствуют) KV>
Нет. Вам приходит на вход object, про который вы точно знаете, что он какой-нибудь IFoo и у него есть метод void Bar(). Его и надо вызвать, ничего не загружая.
Если вы имеете реф на сборку с IFoo, вы можете привести тип или вызвать оператор as, а потом вызывать Bar. А если нет? По идее, вы все знаете про IFoo. Полное имя типа, все сигнатуры, и пр. и др. Можете повторить этот интерфейс дословно и промаркировать его любыми атрибутами (RealTypeName[], например). Но поделиться этим знанием с компилятором не можете, не прибегая к загрузке внешней сборки, где тип описан.
Вопрос в том, можно ли это обойти на уровне языка (я бы посмотрел на реализацию того же as, но не владею IL, а разбираться нет времени), и если можно, то можно ли добавить в Nemerle. Раз авторы не побоялись ввести макросы, то язык занимает нишу "для смелых". Соответственно, сюда и вопрос.
Здравствуйте, <Аноним>, Вы писали:
А>Нет. Вам приходит на вход object, про который вы точно знаете, что он какой-нибудь IFoo и у него есть метод void Bar(). Его и надо вызвать, ничего не загружая.
Вообще-то, именно это и делает приведенный выше пример Test.exe ровным счетом ничего не знает о типе Class1 в обоих сборках, кроме его названия. Сборки же загружаются исключительно потому, что не загрузив их, крайне тяжело вызывать из них какие-либо методы
Вот пример попроще:
using Nemerle.Late;
using System;
using System.Console;
module Program
{
class LengthableObject
{
public Length = 0
}
Main() : void
{
def getLength(o : object)
{
late o.Length;
}
WriteLine(getLength(array[1,2,3]));
WriteLine(getLength([1,2,3,4,5]));
WriteLine(getLength("bla-bla-bla"));
WriteLine(getLength(LengthableObject()));
_ = ReadLine();
}
}
Здравствуйте, kochetkov.vladimir, Вы писали:
KV>Здравствуйте, Ziaw, Вы писали:
Z>>Очередной фичреквест на duck typing. Платформа действительно не позволяет эффективно его реализовать? Хорошо бы подумать над этим.
KV>DLR позволяет. Но я так чувствую, что для начала, надо взять макрос late и внаглую позиционировать его, как "впихнули невпихуемое", т.е. как реализацию динамической типизации безо всяких DLR.
late это самая тормозная утиная типизация из всех возможных. Более эффективной будет создание прокси.
Решение в лоб:
IDuck
{
Swim() : void;
}
SomeDuck
{
public Swim():void {...}
}
[Record]
SomeDuckIDuckProxy : IDuck // Этот класс генерируется автоматически
{
instance : SomeDuck;
public Swim():void {instance.Swim()}
}
module Program()
{
public Swim(duck : duck[IDuck]) : void// передача утиного параметра
{
duck.Swim();
}
// должно развернуться во что-то типа:public Swim([DuckType(typeof(IDuck))] duckObj : object) : void// атрибут позволит компилятору проконтроллировать передачу сюда только тех типов, которые подходят под IDuck
{
def duck = DuckTyping.MakeProxy.[IDuck](duckObj);
duck.Swim();
}
public Main() : void
{
def someDuck = SomeDuck();
def duck = duck[IDuck](someDuck); // вот при таком использовании класс выше и должен сгенерироваться, в duck будет прокси
// в итоге будет такой кодdef duck = SomeDuckIDuckProxy(someDuck) : IDuck;
Swim(someDuck); // Swim(SomeDuckIDuckProxy(someDuck)) // компилятор знает, что там потребуется IDuck, поэтому сразу передает то, что надо
Swim(duck); // Swim(duck)
}
}
module DuckTyping // Этот класс генерируется автоматически
{
public MakeProxy[TDuck](o : object) : TDuck
{
if (o is TDuck)
o :> TDuck // чаще всего будет использована эта веткаelse match (typeof(TDuck), o.GetType()) // грубое описание
{
// тут у нас будет кусок кода который по таблице ищет
| (typeof(IDuck), typeof(SomeDuck)) => SomeDuckIDuckProxy(o :> SomeDuck) :> TDuck
| _ => CreateRuntimeProxy(typeof(TDuck), o); // это самый тяжелый вариант, тип пришел из внешней сборки которая ничего про ducktyping не знает
}
}
}
Тут есть поле для оптимизаций, но уже такой duck typing должен быть быстрее DLR и, тем более, late.
Здравствуйте, Аноним, Вы писали:
А>Проблема, однако, вот в чем. DT должен поддерживаться на обоих концах. Допустим, есть IDispatch с Invoke(string MethodeName). Он должен входить в FW, чтобы и клиент, и сервер его видели (один дергал, другой реализовывал), пусть даже на клиенте язык позволяет прозрачно превращать вызовы в Invoke. Когда последний раз мне это было надо, я спрашивал на форуме .Net, есть ли какой-то подходящий интерфейс, ответ был — нету (действительно нет?). Как бы вы не реализовали DT, в это все упрется.
Такой интерфейс не нужен, рефлекшен покрывает сценарии его использования. Но через рефлекшен все довольно небыстро получается. Похоже тебе не нужен DT, а действительно достаточно late.
Здравствуйте, Аноним, Вы писали:
А>Нет. Вам приходит на вход object, про который вы точно знаете, что он какой-нибудь IFoo и у него есть метод void Bar(). Его и надо вызвать, ничего не загружая.
А как вы хотите вызвать метод Bar, не вызывая сборку, в которой он определен? Это нереально чисто физически. Или же речь идет о том, что у нас есть сбока А с интерфейсом IFoo, сборка B с реализацией IFoo, и вы хотите вызвать метод Bar у реализации, не загружая сборку с интерфейсом?
Так сделать можно. Причем довольно богатым набором способов. Однако за все эти способы придется платить производительностью. Причем, кстати, Немерле вам тут ничего не даст. Немерле дает богатые возможности для мета-программирования в компайл-тайме. Здесь же идет речь о мета-программировании в рантайме, с которым и у того же C# все в порядке. Единственно, что Немерле тут даст — это какой-нибудь синтаксический сахар на подобие late.
А саму вышеозначенную задачу можно решить:
— Напрямую через рефлекшин
— Через прозрачный прокси
— Через Emit (описать *свой* интерфейс IFoo, который *по сути* совместим с тем, который реализует наш Foo, но с т.з. рантайма это разные типы; затем сгенерить на лету обвертку для Foo, реализующую *свой* интерфейс IFoo). Этот способ с одной стороны самый быстрый, с другой стороны — самый медленный. На генерацию враппера уйдет какое-то время, зато потом вызовы будут осуществляться довольно быстро.
— Dynamic (C# 4.0)
Re[4]: Импорт
От:
Аноним
Дата:
21.02.11 09:44
Оценка:
Здравствуйте, Воронков Василий, Вы писали:
А>>Нет. Вам приходит на вход object, про который вы точно знаете, что он какой-нибудь IFoo и у него есть метод void Bar(). Его и надо вызвать, ничего не загружая.
ВВ>А как вы хотите вызвать метод Bar, не вызывая сборку, в которой он определен? Это нереально чисто физически. Или же речь идет о том, что у нас есть сбока А с интерфейсом IFoo, сборка B с реализацией IFoo, и вы хотите вызвать метод Bar у реализации, не загружая сборку с интерфейсом?
Второе.
ВВ>Так сделать можно. Причем довольно богатым набором способов. Однако за все эти способы придется платить производительностью. Причем, кстати, Немерле вам тут ничего не даст. Немерле дает богатые возможности для мета-программирования в компайл-тайме. Здесь же идет речь о мета-программировании в рантайме, с которым и у того же C# все в порядке. Единственно, что Немерле тут даст — это какой-нибудь синтаксический сахар на подобие late.
ВВ>А саму вышеозначенную задачу можно решить: ВВ>- Напрямую через рефлекшин ВВ>- Через прозрачный прокси ВВ>- Через Emit (описать *свой* интерфейс IFoo, который *по сути* совместим с тем, который реализует наш Foo, но с т.з. рантайма это разные типы; затем сгенерить на лету обвертку для Foo, реализующую *свой* интерфейс IFoo). Этот способ с одной стороны самый быстрый, с другой стороны — самый медленный. На генерацию враппера уйдет какое-то время, зато потом вызовы будут осуществляться довольно быстро. ВВ>- Dynamic (C# 4.0)
Я плохой пример привел. Действительно, можно через рефлекшин даже на шарпе. Давайте другой приведу. Как подделать typeof(IFoo) для, например, ремотинга? Еще раз: вся информация нам на клиенте доступна. Гуиды-шмуиды, сигнатуры-шмигнатуры. Все. Выглядит так, что это 100% language hackable feature. Может, ошибаюсь.
Здравствуйте, Ziaw, Вы писали:
Z>Такой интерфейс не нужен, рефлекшен покрывает сценарии его использования. Но через рефлекшен все довольно небыстро получается. Похоже тебе не нужен DT, а действительно достаточно late.
Если клиент берет данные, необходимые в typeof() из третьей сборки, что-то подсказывает мне, что он мог бы брать их и из конфига, и из кода, и даже динамически от сервера через известный интерфейс.
Re[5]: Импорт
От:
Аноним
Дата:
21.02.11 10:24
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Я плохой пример привел. Действительно, можно через рефлекшин даже на шарпе. Давайте другой приведу. Как подделать typeof(IFoo) для, например, ремотинга? Еще раз: вся информация нам на клиенте доступна. Гуиды-шмуиды, сигнатуры-шмигнатуры. Все. Выглядит так, что это 100% language hackable feature. Может, ошибаюсь.
А>
Допустим, такое решение. На этапе компиляции выполняем typeof(IFoo). Побитовое представление полученного объекта сохраняем и зашиваем в сборку. Следовательно, в рантайме typeof можно больше не вызывать, т.к. есть зашитый. Получаем милую фичу "pseudo-reference" ("reference in design-time only").
Здравствуйте, Аноним, Вы писали:
А>Допустим, такое решение. На этапе компиляции выполняем typeof(IFoo). Побитовое представление полученного объекта сохраняем и зашиваем в сборку. Следовательно, в рантайме typeof можно больше не вызывать, т.к. есть зашитый. Получаем милую фичу "pseudo-reference" ("reference in design-time only").
А если попробовать сгенерировать аналогичное побитовое представление в рантайме?
Или даже так — с помощью емита сгенерировать на лету сборку с интерфейсом и подсунуть ее через AssemblyResolve