2014-01-02 1 views
3

Я искал несколько дней и до сих пор не нашел правильного ответа. Я нашел this похожий вопрос, который может двигаться в правильном направлении. Я работаю на C#, используя VS2008, и мне нужно общаться с приложением VB6. Моя проблема заключается в том, что у меня есть несколько классов типа конфигурации, которые мне нужно выставить через COM, чтобы доступ к данным содержал приложение VB6. Я отлично справлялся с этим, пока один из моих классов не должен был выставлять параметр массива класса. Моя C# код что-то вроде этого:Как выставить параметр массива класса COM с помощью Interopservices?

[Guid("..."),InterfaceType(ComInterface.InterfaceIsDual)] 
    public interface iClientComInterop 
    { 
     [DispID(1) Properties GetData(); 
    } 


    [Guid("..."), ClassInterfaceAttribute(ClassInterfaceType.None),ProgIdAttribute("ClientComInterop"),ComDefaultInterfaceAttribute(typeof(iClientComInterop))] 
    public class ClientComInterop : iClientComInterop 
    { 
     public ClientComInterop() 
     { 
     } 
     public Properties GetData() 
     {...} 

    } 
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    [Guid("...")] 
    public interface iProperties 
    { 
     [DispId(1)] 
     int Id{get; } 
     [DispId(2)] 
     ProcessingInformation ProcessingInfo { get; } 
    } 

     [ClassInterface(ClassInterfaceType.None)] 
     [ProgId("ConfigurationTypes.Properties")] 
     [Guid("...")] 
     public class Properties : iProperties 
     { 
     public int Id 
     { 
      get ; 
      set ; 
     } 
     public ProcessingInformation ProcessingInfo 
     { 
      get ; 
      set ; 
     } 

    public Properties() 
    { 
     ... 
    } 
    } 
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    [Guid("...")] 
    public interface iProcessingInformation 
    { 
    [DispId(1)] 
    bool Enabled {get; } 
    [DispId(2)] 
    AccountInformation[] accounts { [return:MarshalAs(UnmanagedType.SafeArray)]get; } 

    } 
    [ClassInterface(ClassInterfaceType.None)] 
    [ProgId("ConfigurationTypes.ProcessingInformation")] 
    [Guid("...")] 
    public class ProcessingInformation : iProcessingInformation 
    { 
    public bool Enabled 
    { 
     get ; 
     set ; 
    } 
    public AccountInformation[] Accounts 
    { 
     get; 
     set; 
    }  
    public ProcessingInformation() 
    { 
     ... 
    } 
    } 
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    [Guid("...")] 
    public interface iAccountInformation 
    { 
    [DispId(1)] 
    int Type {get; } 
    [DispId(2)] 
    double balance{ get; } 
    } 
    [ClassInterface(ClassInterfaceType.None)] 
    [ProgId("ConfigurationTypes.AccountInformation")] 
    [Guid("...")] 
    public class AccountInformation: iAccountInformation 
    { 
    public int Type 
    { 
     get ; 
     set ; 
    } 
    public double balance 
    { 
     get; 
     set; 
    } 
    public AccountInformation() 
    { 
     ... 
    } 
    } 

Это все компилируется, регистры и отображается в обозревателе объектов VB6 ищет правильно, но я не смог получить массив AccountInformation из ProcessingInformation. Я получаю ошибку несоответствия объекта. Эти данные необходимо получить как часть объекта Properties с помощью функции GetData(). Я совершенно не понимаю, как я должен это делать. Я могу вытащить любую другую информацию из Properties и ProcessingInformation, но не информацию в массиве AccountInformation.

VB6 Пример:

Public Client As ClientComInterop.ClientComInteropSet 
Client = CreateObject("ClientComInterop") 
Dim data as ConfigurationTypes.PropertiesSet 
data = Client.GetData() 
Print "ID: " ; data.ID ' This works 
Print "Process enabled: "; data.ProcessingInfo.Enabled ' This works 
Print "Accounts Type: "; data.ProcessingInfo.Accounts(0).Type ' error Type mismatch 

Я пытаюсь несколько других вещей, а также, например, создание локального массива счетов и попытался установить это с data.ProcessingInfo.Accounts. Это тоже не сработало, я получаю ту же ошибку «Тип несоответствия».

Что мне не хватает?

ответ

0

Попробуйте эту подпись для accounts собственности:

AccountInformation[] accounts 
{ 
    [return:MarshalAs(UnmanagedType.SafeArray, 
     SafeArraySubType = VarEnum.VT_VARIANT)] get; 
} 

[UPDATE] у меня нет VB6, но вот то, что работает для меня с VBScript. Я должен признать, что в течение разумного периода времени я потратил на это, я не мог найти лучший способ сделать это, в том числе, как непосредственно доступ к элементу по индексу (т.е. processInfo.Accounts(0)):

VBScript:

' this works: 
For Each a in processInfo.Accounts 
    MsgBox a.balance 
Next 

' this doesn't: 
MsgBox processInfo.Accounts(0) 

C#:

public interface iProcessingInformation 
{ 
    [DispId(2)] 
    object[] Accounts 
    { 
     [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] get; 
     set; 
    } 
} 

public class ProcessingInformation : iProcessingInformation 
{ 
    public object[] Accounts 
    { 
     get 
     { 
      return new object[] { new AccountInformation() }; 
     } 
     set 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 
+0

Спасибо за но это не устраняет проблему. Я теперь не получаю «несоответствие типа ошибки», но я не могу увидеть массив или даже идентифицировать учетные записи как массив в коде VB6, с вышеуказанным заявлением на печать. Ошибка времени выполнения: «Неверное количество аргументов или недопустимое присвоение свойств». Если я создам массив типа Variant в моем коде VB6 и попытаюсь установить это с данными из data.ProcessingInfo.Accounts, я все равно получаю ошибку несоответствия типа. – TaterTot

+0

@TaterTot, см. Мое обновление. – Noseratio

+1

@ Norseratio, Спасибо за ваши дальнейшие усилия. Извините, я так долго возвращался к этому. К сожалению, это не похоже на решение в этом случае. Единственный способ, который я нашел, который позволит мне получить доступ к любой из фактических данных в массиве, - это изменить интерфейс класса на ProcessingInformation от None до AutoDual. Это не лучший случай для меня, он позволяет получить доступ к другому элементу в ProcessingInformation, которые не являются частью интерфейса. – TaterTot

 Смежные вопросы

  • Нет связанных вопросов^_^