Почему не всегда доступен индексатор на моем компоненте.NET от VBScript?

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

Я сделал реализацию, но фактическая часть группировки и отображения не оптимизирована. Я решаю твою проблему жестко

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int     main() {
  int       matched = 0;
  int       n_words = 0;
  char**    words = NULL;
  int*      masks = NULL;
  int       max_mask = 0;

  while (1) { // Read until EOF breaks
      char word[30];
      if (scanf("%s\n", word) == EOF)
        break;
      words = realloc(words, sizeof(char *) * (n_words + 1));
      words[n_words] = strndup(word, 30);
      n_words++;
  }

  // Computes a bit mask for each word
  masks = malloc(sizeof(int) * n_words);
  for (int i = 0; i < n_words; ++i) {
    masks[i] = 0;    
    for (int j = 0; words[i][j] != '\0'; ++j) {
      int bit_index = words[i][j] - 'a';
      masks[i] |= (1 << bit_index);
    }
    if (masks[i] > max_mask)
      max_mask = masks[i];
  }

  // Iterate over each possible masks and print all words with this mask
  for(int i = 0; i <= max_mask; i++) {
    for (int w = 0; w < n_words; w++) {
      if (masks[w] == i) {
        printf("%s ", words[w]);
        matched = 1;
      }
    }
    if (matched) {
      printf("\n");
      matched = 0;
    }
  }
  return 0;
}
7
задан Community 23 May 2017 в 12:01
поделиться

4 ответа

Я наткнулся на эту точную проблему несколько дней назад. Я не мог найти разумного объяснения, почему это не работает.

Проведя долгие часы, пробуя разные обходные пути, я думаю, что наконец нашел что-то, что, кажется, работает, и не так уж и грязно. Я реализовал метод доступа к коллекции в объекте-контейнере как метод, а не свойство. Этот метод получает один аргумент - ключ. Если ключ «отсутствует» или равен нулю, то метод возвращает коллекцию (это обрабатывает такие выражения, как «testRequest.QueryString.Count» в VbScript). В противном случае метод возвращает конкретный элемент из коллекции.

Грязная часть этого подхода состоит в том, что этот метод возвращает объект (поскольку иногда возвращаемой ссылкой является коллекция, а иногда и элемент коллекции), поэтому для его использования из управляемого кода требуется повсеместное приведение типов. Чтобы избежать этого, я создал другое свойство (на этот раз правильное свойство) в контейнере, который представляет коллекцию. Это свойство НЕ предоставляется COM. Я использую это свойство из C # / управляемого кода, а из COM / VbScript / неуправляемого кода я использую метод.

Вот реализация вышеуказанного обходного пути на примере этого потока:

  [ComVisible(true)]
  [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  public interface IRequest
  {
    IRequestDictionary ManagedQueryString { get; } // Property to use form managed code
    object QueryString(object key); // Property to use from COM or unmanaged code
  }

  [ComVisible(true)]
  [ClassInterface(ClassInterfaceType.None)]
  public class TestRequest : IRequest
  {
    private IRequestDictionary _queryString = new RequestDictionary();

    public IRequestDictionary ManagedQueryString
    {
      get { return _queryString; }
    }

    public object QueryString(object key)
    {
      if (key is System.Reflection.Missing || key == null)
        return _queryString;
      else
        return _queryString[key];
    }
  }

  [ComVisible(true)]
  [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  public interface IRequestDictionary : IEnumerable
  {
    [DispId(0)]
    object this[object key]
    {
      [DispId(0)]
      get;
      [DispId(0)]
      set;
    }

    int Count { get; }
  }

  [ComVisible(true)]
  [ClassInterface(ClassInterfaceType.None)]
  public class RequestDictionary : IRequestDictionary
  {
    private Hashtable _dictionary = new Hashtable();

    public object this[object key]
    {
      get { return _dictionary[key]; }
      set { _dictionary[key] = value; }
    }

    public int Count { get { return _dictionary.Count; } }

    #region IEnumerable Members

    public IEnumerator GetEnumerator()
    {
      throw new NotImplementedException();
    }

    #endregion
  }
5
ответ дан 6 December 2019 в 11:53
поделиться

КАЧАЙТЕ здесь... Вы исследовали свой блок с oleview, чтобы удостовериться, что Ваш открытый интерфейс имеет индексатор, видимый com потребителям? Второй ВЗМАХ должен использовать get_Item метод непосредственно, вместо того, чтобы пытаться использовать свойство индексатора (проблемы совместимости с CLS)...

1
ответ дан 6 December 2019 в 11:53
поделиться

Я нашел это testRequest.QueryString()("key") работы, но что я хочу, testRequest.QueryString("key").

Я нашел очень соответствующую статью Eric Lippert (у кого есть некоторые действительно большие статьи о VBScript, между прочим). Статья, Семантика Свойства Значения по умолчанию VBScript, обсуждает условия для того, вызвать ли свойство по умолчанию или просто вызов метода. Мой код ведет себя как вызов метода, хотя это, кажется, удовлетворяет условиям для свойства по умолчанию.

Вот правила от статьи Eric:

Правило для реализаторов IDispatch:: Вызовите то, если все следующее верно:

  • вызывающая сторона вызывает свойство
  • вызывающая сторона передает список аргументов
  • свойство на самом деле не берет список аргументов
  • то свойство возвращает объект
  • тот объект имеет свойство по умолчанию
  • то свойство по умолчанию берет список аргументов

затем вызовите свойство по умолчанию со списком аргументов.

Кто-либо может сказать, не соблюдают ли какое-либо из этих условий? Или могло быть возможно что реализация.NET по умолчанию IDispatch.Invoke ведет себя по-другому? Какие-либо предложения?

1
ответ дан 6 December 2019 в 11:53
поделиться

Я потратил пару дней на решение одной и той же проблемы, пробуя все возможные варианты, используя несколько тактик. Это сообщение решило мою проблему:

следующее использовалось для генерации ошибки parentobj.childobj (0) ранее приходилось делать: parentobj.childobj.item (0)

путем изменения:

Default Public ReadOnly Property Item(ByVal key As Object) As string
    Get
        Return strSomeVal

    End Get
End Property

на:

Public Function Fields(Optional ByVal key As Object = Nothing) As Object

    If key Is Nothing Then
        Return New clsFieldProperties(_dtData.Columns.Count)
    Else
        Return strarray(key)
    End If
End Function

, где:

Открытый класс clsFieldProperties Частный _intCount как целое число

Sub New(ByVal intCount As Integer)
    _intCount = intCount

End Sub
Public ReadOnly Property Count() As Integer
    Get
        Return _intCount
    End Get
End Property

Конечный класс

1
ответ дан 6 December 2019 в 11:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: