为什么不Marshal.请在我的COM对象上调用Release?

Mot*_*tti 1 .net c# com interop

我已阅读文档,Marshal.GetIUnknownForObject并说:

Marshal.Release完成指针后,始终使用减少引用计数.

我写了,我通过.NET中使用COM对象的测试解决方案,我看到与工作时的包装,以我的COM对象既不Marshal.GetIUnknownForObject也不Marshal.Release引起AddRefRelease我的COM对象的方法被调用.

那是怎么回事?

Eri*_*ert 6

等一下,我想我已经明白了.你正在创建一个COM对象,然后你在这个COM对象周围创建一个运行时可调用包装器,然后你要求运行时可调用包装器为它的朋克,然后你想知道为什么在那个朋克上调用release不会调用你的发布?这总结了你的问题吗?

如果是这样,你可能已经在问题中提到了所有这些细节而不是让我们猜测.

好吧,为什么你认为它会调用你的版本?它将调用运行时可调用包装器的Release .包装器包裹你的对象; 这就是为什么它被称为包装器.运行时可调用包装并不需要对AddRef和每次释放你的对象被addref'd并发布了!为什么会这样?它需要让你的对象保持活着,它已经有你的对象的引用 ; 这足以使包裹的物体保持活力.为什么不必要的工作?

当你只有一个COM对象周围的运行时可调用包装器时,你应该合理地期望对象的ref计数在对象的整个生命周期内是不变的.运行时接受一次ref,当RCW最后一次被垃圾收集或以其他方式释放时,它会释放ref并且对象会自行删除.

想想这样.假设你说:

foo->bar = blah;
blah->AddRef();
Run Code Online (Sandbox Code Playgroud)

blah得到addref'd因为foo-> bar有引用它.现在你说:

abc->def = foo;
foo->AddRef();
Run Code Online (Sandbox Code Playgroud)

这增加了foo的参考.它是否添加了参考等等?当然不是.为什么会这样?foo有一个基础; foo被abc保持活着的事实与blah无关.

这里也是一样的.你有:

wrapper = new RCW();
wrapper->wrapped = yourobject;
yourobject->AddRef();
Run Code Online (Sandbox Code Playgroud)

这为你提供了一个参考.现在,如果你有

wrapper->QI(IUnknown, &punk)
Run Code Online (Sandbox Code Playgroud)

它不会给你底层对象的朋克,它会给你包装器的朋克.如果你说

punk->AddRef();
Run Code Online (Sandbox Code Playgroud)

如果没有addref底层对象,它会添加包装器.