Обобщения были добавлены в .NET 2.0, а COM существовал до .NET 1.0.
(И была технология .NET , предназначенная для замены .)
COM никогда не имел обобщения,и, следовательно, вы не можете их выставить.
Ни у одного из языков COM (C ++, VB6, Delphi) не было обобщений, поэтому вы не можете ожидать, что они будут использованы.
(Ну, у C ++ были шаблоны, но они совершенно другой зверьи COM означает только интерфейсы .)
Предоставление коллекций в виде ArrayList
является решением для этой проблемы, вы не можетеобойти это.
Отказ от ответственности : я не эксперт по COM, поэтому остальная часть ответа примерно основана на моих догадках.
COMникогда не «имел» ArrayList
с, правда, но поэтому никогда не было любых классов в .NET Framework, потому что это не сама платформа.Однако некоторые из типов .NET попадают в экспортируемые библиотеки типов, а некоторые - нет.А как насчет классов .NET Framework?Ну, ArrayList
- это [ComVisible]
, а List<T>
- нет.
Почему?
COM работает через интерфейсы , а язык определения интерфейсов не имеет представления о дженериках и не поддерживает их.Языки, которые поддерживают COM, такие как VB6 или C ++, не будут знать, что делать с универсальными шаблонами.
Если бы был способ создать интерфейс для List<T>
, он не содержат T
в нем, так что нет смысла пытаться раскрыть универсальный тип.Возможные мнимые альтернативы этому:
- Генерация «определенной» версии интерфейса для универсального типа, например,
IListOfString
для List<string>
- Стирание информации универсального типа (значительнокак Java это делает при компиляции) и заменой
T
на object
.
Первый вариант недопустим, поскольку конкретный тип T
может быть неизвестен при компиляции (читай: Reflection),и List<T>
все равно не имеет атрибута [ComVisible]
.
Второй вариант фактически возможен, потому что вы можете предоставить свой собственный интерфейс класса с IList
и ICollection
properties :
[ComVisible(true)]
public interface IPerson
{
string Name { get;set;}
DateTime Entered { get;set;}
IList NickNamesList { get;}
ICollection NickNamesCollection { get;}
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComDefaultInterface(typeof(IPerson))]
public class Person:IPerson
{
[ComVisible(false)]
public List<string> NickNames
{
get { return _NickNames; }
set { _NickNames = value; }
}
private List<string> _NickNames = new List<string>();
#region IPerson Members
IList IPerson.NickNamesList
{
get { return this.NickNames; }
}
ICollection IPerson.NickNamesCollection
{
get { return this.NickNames; }
}
#endregion
....
}
Это обходной путь, но он не отвечает на ваш вопрос.
Мне действительно интересно, могли бы вы получить класс StringList
из List<string>
и отметьте его как [ComVisible(true)]
.Вы можете проверить это.