В чем проблема с классом взаимодействия как параметром универсального типа? - PullRequest
3 голосов
/ 25 марта 2011

У меня есть базовый базовый класс-обертка, чтобы обернуть пару используемых нами ком-компонентов:

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

Я получаю (двойную) ошибку компиляции:

  • ошибка CS0012: тип 'ComponentsAssembly.CUserClass' определен в сборке, на которую нет ссылок. Вы должны добавить ссылку на сборку «Interop.ComponentsAssembly, Версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = ... '.
  • ComponentWrappers.dll: (Связанный файл) Ошибка CS0310: «ComponentsAssembly.CUserClass» должен быть не абстрактный тип с открытым конструктором без параметров для того, чтобы используйте его как параметр 'T' в универсальном типе или методе 'Contact.Wrappers.WrapperBase'

Я пытался добавить ссылку на компонент, но все равно получаю то же сообщение об ошибке.

Раньше это работало до того, как я изменил WrapperBase на универсальный тип, но затем было много кода, идентичного во всех конкретных оболочках, поэтому я реорганизовал его, сделав WrapperBase универсальным.

Я действительно могу решить эту проблему, добавив конструктор к конкретному классу, который принимает в качестве параметра «ComponentParameters» и вызывает внутренние параметры SetParameters:

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

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

И затем использовать это так:

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

Но я бы предпочел, чтобы оба метода работали (используя конструктор и явно вызывая SetParameters).

Может ли кто-нибудь объяснить мне, что именно здесь происходит, поскольку я в течение последних нескольких часов бился головой о стену.

1 Ответ

3 голосов
/ 25 марта 2011

Попробуйте: при добавлении ссылки COM в ComponentWrappers.dll она создает сборку взаимодействия для нее и помещает ее в место сборки (bin / release независимо) для этой сборки. В основном перейдите к этому местоположению и добавьте ссылку .NET (не ссылку COM) и перейдите к этому месту сборки и возьмите взаимодействие в качестве ссылки.

Я думаю, что это может сбить с толку, потому что вы добавили его как COM в обоих местах, и это сгенерировало взаимодействие в каждом ...

Другой вариант - полностью исключить публичный доступ к артефакту COM за пределами вашей сборки. Для этого вам нужно скрыть это внутри класса и т. Д.

...