2016-12-05 12 views
2

私はVBAプログラムで使用しているC#、Visual Studio 2010、.NET 3.5、x86 でCOMオブジェクトを開発しています。VBからのCOMオブジェクト配列

namespace Test 
{ 
    [Guid("8b65089f-5d98-41e7-9579-1ee384948e4c")] 
    [ComVisible(true)] 
    [StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public struct Contact 
    { 
     [MarshalAs(UnmanagedType.BStr)] 
     public string Test1; 
     public string[] Array; 
    } 


    [Guid("8b65082f-5d98-41e7-9579-1ee384948e4e"), ComVisible(true)] 
    public interface IInContainer 
    { 
     Contact[] Contacts { [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] get; set; } 
     string[] strings { [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] get; set; } 

    } 

    [Guid("8b65089f-5d98-41e7-9579-1ee384948e4b"), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)] 
    public class InContainer 
    { 
     //[MarshalAs(UnmanagedType.BStr)] 
     public Contact[] Contacts { get;set;} 
     public string[] strings { get; set; } 
    } 

} 

VBでオブジェクトの構造/インタフェースを見ることができます。

私はContainer.stringsの情報をVBからVBで変更することができます。

しかし、VB経由でContact配列(Contact構造体を使用)の情報を変更することはできません。

連絡先配列は長さが1で、そのノードのすべての値が「テスト」に設定されているとします。 VB経由で変更しようとしたとき、つまりContainer.Contact(0).Test1 = "Monkey"はエラーになりません。つまり、Print(Container.Contact(0).Test1)の直後にそれを読み込もうとすると、私は "" "などの何らかのデフォルト文字列を取得します。

私は連絡先の情報をコンテナオブジェクトのメソッドを使用して変更できますが、これは望ましくありません。

私はなぜ値がContainer.Contact配列でのみ読み込まれるのか助けが必要です。

+0

"望ましくない"ということを避けるために、実際には約十ダースの方法を使用するコードを書いたことがありますが、依然として仕事を完了することはありません。これのポイントは何でしたか?あなたは実際に*コードのコストを測定しましたか?あなたの選択肢が何千倍も遅いことを知るための本当の方法は、VBAはどんな種類のコードが実行されているかを知る他の良い方法を提供しません。 –

答えて

2

基本的に構造体のコピーを編集しています。これは、代入後に直接破棄されます(変数に保持されないため)。

インデックス0の Contactアイテムのコピーが作成され
  • プロパティTest1に値が割り当てられている
  • (構造体は値型であるため)」:あなたはContainer.Contact(0).Test1 = "Monkey"では、次の取得何を分解する場合

    連絡先のコピーの猿」

  • Whのを捨てている修正Test1プロパティとの接触構造体のコピー配列Print(Container.Contact(0).Test1)を呼び出すと、配列内の元のContact構造体が再度コピーされ、この新しく作成されたコピーのTest1プロパティが出力されます。

一つの解決策は、クラスに構造体からあなたContactタイプを変更するか、だけではなく、単一のプロパティまたはフィールドを変更しようとしているの指定した配列インデックスの位置struct全体を交換することです。

dim cntct as Contact 
cntct = Container.Contact(0) 
cntct.Test1 = "Monkey" 
Container.Contact(0) = cntct 

あなたは確かに構造体が、おそらくクラスに構造体から変更したい、ここで必要とされることが確実でない限り。

+0

答えをありがとう! Contactにコンタクトを作成したクラスに変更しましたが、構文エラーが発生しました: "間違ったパラメータ数" @ 'Container.Contacts(0).Test1 =" Monkey "'。残りは同じ考え方にとどまりますか? – PonWer

+0

getterとsetterで 'Test1'をプロパティとして定義しましたか?' public string Test1 {get;セット; }; '? –

+0

プロパティとインターフェイスを持つクラスへの完全な変換 – PonWer

関連する問題