开发者

What's the problem with an interop class as a generic type parameter?

开发者 https://www.devze.com 2023-02-19 14:36 出处:网络
I have a generic base wrapper class to wrap a couple of com components we\'re using: public class WrapperBase<T> : IDisposable

I have a generic base wrapper class to wrap a couple of com components we're using:

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;
    }

    // ... 
}

Now I have a concrete wrapper class which inherits from this base class:

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

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

The type used (CUserClass) is a COM interop type. This type is available after adding the COM object as a reference to the project.

Now I use this class in another assembly (which references the assembly in which the above types are defined):

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

The above code compiles fine, but if I'm actually calling the SetParameters method (which is only defined in the Wrapperbase class):

using (var user = new UserWrapper())
{
    user.SetParameters(someParameters开发者_JS百科);
}

I get a (double) compilation error:

  • 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'

I've tried adding a reference to the component, but I still get the same error message.

This used to work before I changed the WrapperBase to a generic type, but then there was a lot of code identical in all the concrete wrappers, so I refactored it, making the WrapperBase generic in the process.

I can actually solve this by adding a constructor to the concrete class which takes a "ComponentParameters" as a parameter and calls the SetParameters internally:

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

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

And then using it like this:

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

But I'd rather have both methods working (using a constructor and explicitly calling SetParameters).

Can anybody explain to me what exactly is happening here, as I've been banging my head against the wall for the last couple of hours.


Try this: when you add the COM reference in ComponentWrappers.dll, it generates an interop assembly for it and puts it in the build location (bin/release whatever) for that assembly. In main, navigate to that location and add a a .NET reference (not COM reference) and navigate to that build location and take the interop as the reference.

I think it may be getting confused because you added it as COM in both places and it generated an interop in each...

The other option is to completely prevent the COM artifact from having any public visibility outside your assembly. To do this you'd have to hide it internally in a class, etc.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号