2011-03-25 79 views
3

我有一个通用的基础包装类来封装夫妇COM组件,我们使用:互操作类作为泛型类型参数时出现什么问题?

public class WrapperBase<T> : IDisposable 
    where T : new() 
{ 
    private T comObject = default(T); 
    private ComponentParameters parameters = null; 

    protected WrapperBase() 
    { 
     comObject = new T(); 
     Initialize(); 
    } 

    public void SetParameters(ComponentParameters parameters) 
    { 
     // ... 
     this.parameters = parameters; 
    } 

    // ... 
} 

现在我有一个具体的包装类从这个基类继承:

public class UserWrapper : WrapperBase<CUserClass> 
{ 
    public UserWrapper() : base() { } 

    public void SomeUserWrapperMethod() 
    { 
     // ... 
    } 
} 

的使用的类型(CUserClass)是COM互操作类型。添加COM对象作为项目的引用后,此类型可用。

现在,我使用这个类在其他组件(它引用了上述类型定义的组件):

using (var user = new UserWrapper()) 
{ 
    user.SomeUserWrapperMethod(); 
} 

上面的代码编译罚款,但如果我实际调用SetParameters方法(这是只有在Wrapperbase类中定义):

using (var user = new UserWrapper()) 
{ 
    user.SetParameters(someParameters); 
} 

我得到了(双)编译错误:

  • error CS0012: The type 'ComponentsAssembly.CUserClass' is defined in an assembly that is not referenced. You must add a reference to assembly 'Interop.ComponentsAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=...'.
  • ComponentWrappers.dll: (Related file) error CS0310: 'ComponentsAssembly.CUserClass' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Contact.Wrappers.WrapperBase'

我试着添加对组件的引用,但仍然收到相同的错误消息。

在我将WrapperBase更改为泛型类型之前,它曾用于工作,但后来在所有具体包装中存在大量相同的代码,所以我重构了它,使WrapperBase在过程中成为泛型。

public class UserWrapper : WrapperBase<CUserClass> 
{ 
    public UserWrapper() : base() { } 

    public UserWrapper(ComponentParameters parameters) : base() 
    { 
     SetParameters(parameters) 
    } 
} 

,然后使用它像这样:

using (var user = new UserWrapper(someParameters)) 
{ 
    user.SomeUserWrapperMethod(); 
} 

我其实可以通过增加一个构造函数的具体类,这需要“ComponentParameters”作为参数,并调用内部的SetParameters解决这个问题

但我宁愿有两个方法工作(使用构造函数和明确调用SetParameters)。

有人可以向我解释这里发生了什么,因为在过去的几个小时里,我一直在撞墙。

+0

因此,让我直截了当地说,WrapperBase <>是在ComponentWrappers.dll程序集中定义的,但实际上是在某种类型的主程序正确吗?您在主程序本身中添加了对interop的引用,而不是COmponentWrapper.dll? – 2011-03-25 16:15:04

+0

@詹姆斯:不完全。 WrapperBase <>和UserWrapper都在ComponentWrappers.dll中,COM互操作DLL只在ComponentWrappers.dll中引用。在主程序中,我只使用UserWrapper类(并引用了ComponentWrappers.dll)。但即使我在主程序中添加了对interop dll的引用,仍然会得到相同的编译错误。 – fretje 2011-03-25 16:17:21

+0

您是否尝试过将互操作程序集的引用添加到主程序中? – 2011-03-25 16:19:54

回答

3

试试这个:当您在ComponentWrappers.dll中添加COM引用时,它会为它生成一个interop程序集,并将其放入该程序集的构建位置(bin/release whatever)。在main中,导航到该位置并添加一个.NET引用(不是COM引用)并导航到该构建位置并将interop作为参考。

我认为这可能是感到困惑,因为你在这两个地方增加一条,作为COM和它产生在每一个互操作...

另一种选择是完全防止COM神器外界有任何公开的知名度你的装配。要做到这一点,你必须在课堂上内部隐藏它等。

+0

(让我知道如果这没有意义,我可以进一步阐述)。本质上在ComponentWrappers.dll - >添加COM参考,主要添加在ComponentWrappers.dll的构建位置创建的互操作参考... – 2011-03-25 16:27:42

+0

好的,谢谢!这实际上做了窍门(添加引用,浏览生成文件夹选择实际的互操作DLL)。但我想知道是否没有办法来防止这种情况。另外,当我从调试文件夹中选择interop dll时,这会不会给发布版本带来问题,或者反过来呢? – fretje 2011-03-25 16:34:43

+0

通常,当我看到完成时,我看到人们在一个程序集中完全隔离对COM类的引用,所以它不会流血,或者将互操作存储在单独的位置。您可以直接从命令行生成互操作,然后像对待其他任何第三方程序集一样对待它。或者有一个构建步骤创建它,并将其放置在给定的构建位置,然后让这两个程序集直接引用interop。 – 2011-03-25 17:41:14