2013-05-17 15 views
6

私はVB6で消費しているC#4.0でCOM可視のクラスライブラリを作成しました。私がVB6 オブジェクトブラウザを開いて、公開されたメンバーを見ると、私は個々の公開されたメンバーごとにイベントを見ています... しかし、C#コードはそれらを定義していませんVB6/COM Interop:これらのイベントはどこから来ますか?

これは正常ですか?私は何か間違っているのですか?

[ClassInterface(ClassInterfaceType.None)] 
[ComSourceInterfaces(typeof(IMyClass))] 
public class MyClass : IMyClass 
{ 
    public void DoSomething(string someParam) 
    { 
     ... 
    } 
} 

public interface IMyClass 
{ 
    void DoSomething(string someParam); 
} 

アセンブリは厳密な名前のキーで署名され、AssemblyInfo.cs[assembly: ComVisible(true)]属性が設定されているが、私はそれが問題とは何かを持っているかわかりません。

私はVB6でオブジェクトブラウザを見てみると、私は、MyClassのメンバーとしてDoSomething(string)を見て期待しと私はを行うことになる、しかし、私はすべての暴露のために、一致するシグネチャを持つイベントを見てよメソッド、Event DoSomething(someParam As String)のメンバーとしてMyClass

さらに(少なくとも私には)不可解な、特性はまた、「マッチング」イベントを(のみけれども少し稲妻のアイコンから伝えることができます)持っている - MyClassはこのようなプロパティが定義されている場合:

public string SomeProperty { get; set; } 

VB6オブジェクトブラウザでは、 "イベント"はProperty SomeProperty As Stringと定義されていますが、これは私には気まずい思いです。 "プロパティ" 1)が重複し、2)オブジェクトブラウザに "イベント"アイコンが表示されます。読み込み専用のプロパティ/イベントを持つ取得専用のプロパティにも同じことが当てはまります。

これらのイベントはどこから発生し、どのように取り除かれますか?

UPDATE画像は千の言葉の価値がある:

COM Interop - bogus events

UPDATE間違ったことは誤っComDefaultInterface属性の代わりに使用されていたComSourceInterfaces属性でした。期待される結果は、後者の元を与えるスワッピング:ComSourceInterfaceへの引数としてtypeof(IMyClass)を渡すことで

COM Interop - correct members

+0

これは本質的にはタイプミスであることを考えると、私はこれをローカライズし過ぎたものとして閉じようとしています。私はそれを削除することをお勧めします。 – Deanna

+0

@Deanna実際にはタイプミスですが、私はCOMにイベントを公開することについて何かを学びました。私はあなたが正しいと思っています.COMのイベントをCOMに公開することについてのたくさんのSOの投稿がなければなりません...削除される価値はありません:) –

+2

@Deanna私はこれを削除すべきだとは思わない。タイプミスですが、COM interopの初心者である他の人を混乱させる可能性があります。私もそれから何かを学びました。 – MarkJ

答えて

8

あなたはIMyClassのすべてがイベントであることを言っている属性。

クラスのイベントインターフェイスを必要としない場合は、ComSourceInterface属性を削除します。

あなたはは、次の操作を行い、その後VBにあなたのC#クラスからのイベントを公開したくない場合:

あなたはCOM見えるクラスを作成するときにも、単にイベントハンドラを定義するインターフェイスを作成したいと思いますあなたのクラスのために。あなたのクラスはイベントハンドラインタフェースを指定するCOMSourceInterfaceで装飾され、イベントを定義し、イベントハンドラインタフェースを実装する必要があります。別の例については、How To: Raise Events Handled by a COM sinkを参照してください。

[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ] 
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] 
public interface MyEvents 
{ 
    void ConnectedEvent(string state); 
} 


[ComSourceInterfaces(typeof(MyEvents))] 
public class MyClass 
{ 
    public event Action<string> ConnectedEvent; 

    public MyClass() { } 

    public void DoSomething(string state) 
    { 
     if (ConnectedEvent != null) 
      ConnectedEvent(state); 
    } 
} 

も参照してください:Murat's Corner: Exposing COM Events

+1

私はCOMにC#イベントを公開していませんが、この投稿のおかげで、私はそうする必要があるときに必ず戻ってきます...しかし、私はそれを受け入れることができません答えとして* C#コードのどこにもイベントがありません* ...そして、質問はそれらのCOM/VB6イベントがどこから来ているのかということです。私はupvoteが* this *の質問の* this *の答えのために保証されるとは思わない。しかし、COM/VB6にC#イベントを公開するように頼んだら、これはすばらしい答えになります。回答を編集する場合は、追加して投稿を編集してください。それはまだ価値のある情報ですが、少し話題があります。 –

+3

@retailcoderですが、あなたは 'ComSourceInterfaces'属性を使用しました。これはtlbexportに、オブジェクトがそのインタフェースで与えられたイベントをソースできることを伝えます。 – Deanna

+1

@retailcoder私の答えの意味は、ComSourceInterface属性を使ってイベントインターフェイスを指定したことです。イベント接続ポイントを公開しない場合は、削除します。 –

8

あなたは基本的にCOMのイベントについて何か特別なことがないことを見つけています。 COMの何かと同様に、イベントはインターフェイスによってサポートされます。イベントメソッドを指定するインターフェイスについて特別なのは、タイプライブラリの[source]属性でマークされていることだけです。 [ComSourceInterfaces]属性は、タイプライブラリを生成するときにTlbexp.exeによって認識されるすべてです。

COMのプロパティについて特に何もありません。 .NETの場合と同じように動作し、のメソッドで実装されています。ゲッターとセッターメソッド。

VB6はあなたのタイプライブラリを見て、[source]属性とのインターフェースを持っているのでイベントを持つクラスに満足しています。そして、メソッドを持つインターフェースについては満足しています。すべてのメソッドを持つことができるので、イベントが発生したときに実行されるメソッドであるとみなされます。そうでなければ、それらのメソッドがプロパティのアクセサでもあることを認識するのに十分なほどスマートではありません。タイプライブラリの作者が自分が何をしているかを知っていることを前提としています。

イベントは、COMでは「接続ポイント」と呼ばれます。 Google IConnectionPointについて詳しくは、Google IConnectionPointをご覧ください。カスタムイベントアクセサを使用してWinRTコンポーネントを作成した場合、COMイベントに.NETイベントとほとんど共通点がないこともわかります。

Anyhoo、回避策は簡単です。イベントを発生させるときに[ComSourceInterface]を使用してください。

+0

クラスがジェネリック型から派生すると、* ComSourceInterfaceAttribute * ...がこの "副作用"を期待していなかった理由です!説明をありがとう、私は今日何かを学んだ! –

+0

COMはジェネリックをサポートしていないため、型引数のない具体的なクラスだけが[ComVisible]になります。 –

+0

ああ!私は間違いがあります: '[ComSourceInterface]'と '[ComDefaultInterface]' - '型ライブラリエクスポータがジェネリック型から派生し、[...]としてマークされていない型を見つけましたClassInterfaceType.None [... ] [ComDefaultInterface]属性を使用して、明示的なインターフェイスをCOMへの既定のインターフェイスとして公開することを検討してください。 ... COMがジェネリックをサポートしていないことは分かっていますが、私は "クラス*がジェネリック型から派生するとき"と書いています。 –

関連する問題