почему мой клиент C #, использующий библиотеку A, должен иметь оператор использования для библиотеки B (которую использует A) - PullRequest
1 голос
/ 21 мая 2010

у меня есть:

  • Основной класс программы - использует библиотеку A
  • Библиотека A - имеет частичные классы, которые смешиваются в методах из Библиотеки B
  • Библиотека B - сочетание методов и интерфейсов

Так, в Библиотеке B, когда я включаю частичный класс Node, который реализует INode (определенный в Библиотеке B), я внезапно получаю сообщение об ошибке в своем основном классе, где он использует Node из Библиотеки A. Ошибка говорит мне о том, что у меня есть Основной класс иметь заявление об использовании в библиотеке B.

Есть идеи?

РЕДАКТИРОВАТЬ - кроме кода

    // *** PROGRAM ***
    class Program
    {
        static void Main(string[] args)
        {
            var context = new Model1Container();
            Node myNode;  // ** WITHOUT A using for Library B I have an error here ***
         }
     }


// ** LIBRARY A
namespace TopologyDAL
{
    public partial class Node
    {
        // Auto generated from EF
    }

    public partial class Node : INode<int>   // to add extension methods from Library B
    {
        public int Key
    }
}

// ** LIBRARY B
namespace ToplogyLibrary
{
    public static class NodeExtns
    {
        public static void FromNodeMixin<T>(this INode<T> node) {
           // XXXX
        }
    }
    public interface INode<T> 
    {
        // Properties
        T Key { get; }

        // Methods
    }

}

РЕДАКТИРОВАТЬ 2 - Чтобы уточнить, была ли это ссылка или с использованием ошибки:

Итак, ошибка, которая появляется против "Node myNode;" строка:

Ошибка 1 Тип 'Topology.INode`1' определен в сборка, на которую нет ссылок. Вы должны добавить ссылку на сборку 'Топология, Версия = 1.0.0.0, Culture = нейтрально, PublicKeyToken = нуль. U: \ Мои Dropbox \ source \ ToplogyLibrary \ TopologyDAL_ConsoleTest \ Program.cs 11 13 TopologyDAL_ConsoleTest

Когда я позволяю VS исправить это для меня, он добавляет Library2 в качестве ссылки. То есть в клиентском коде нет «использования» ни до, ни после. Таким образом, проблема - ссылка, не использующая проблему.

РЕДАКТИРОВАТЬ 3 - Не конкретно об этом вопросе, однако теперь я заметил, что в программном проекте я не вижу методов mixin (из библиотеки B), если у меня нет оператора using для библиотеки B? Я мог бы создать отдельный вопрос об этом.

Ответы [ 6 ]

5 голосов
/ 21 мая 2010

Я понимаю, что происходит, когда вы ссылаетесь только на библиотеку A из программы Main, и компилятор говорит вам, что нужно добавить ссылку на библиотеку B, потому что некоторые типы, которые предоставляет библиотека A, определены в библиотеке B.

Чтобы исправить это, добавьте ссылку на библиотеку B в основной программный проект.

Вот небольшая диаграмма. Если библиотека A предоставляет тип, определенный в библиотеке B, то Main должен также ссылаться на библиотеку B. Следующая ситуация не будет работать:

_____________             _____________               _____________
| Main       |references  | Library A  |references    | Library B  |
|           -|------------|->         -|--------------|->          |
|            |            | public     |              | SomeType   |
|            |            |  SomeType  |              |            |
|            |            |            |              |            |
-------------             -------------               -------------

Эта проблема возникает только тогда, когда тип, определенный в библиотеке B, доступен через библиотеку A. Это может произойти в одной из следующих ситуаций:

  • РЕДАКТИРОВАНИЕ Тип, определенный в библиотеке A (Node), происходит от типа в библиотеке B (INode<int>).
  • Метод, определенный в библиотеке A, использует тип из библиотеки B в качестве возвращаемого типа или в качестве аргумента.
  • Тип, определенный в библиотеке A, предоставляет тип из библиотеки B как свойство или открытое поле.

Для компиляции вам потребуется добавить ссылку на Assembly3 из Assembly1.

_____________             _____________               _____________
| Main       |references  | Library A  |references    | Library B  |
|           -|------------|->         -|--------------|->          |
|            |            | public     |              | SomeType   |
|            |references  |  SomeType  |              |            |
|           -|------------|------------|--------------|->          |
|            |            |            |              |            |
-------------             -------------               -------------
5 голосов
/ 21 мая 2010

Если LibraryA предоставляет свойства, возвращает объекты из методов или принимает параметры типов, определенных в LibraryB, и вы объявляете или используете переменную в Main Program одного из этих типов, вам понадобится оператор using.

1 голос
/ 21 мая 2010

Поскольку библиотека A использует смесь методов и интерфейсов из библиотеки B, требуется оператор using, если библиотека A и библиотека B существуют в разных пространствах имен, именно так работает C #. Компилятор должен знать, где найти типы библиотеки B, которые используются в библиотеке A.

0 голосов
/ 11 ноября 2015

Как правильно объяснили другие ответы, вашей основной программе требуется ссылка на библиотеку B, поскольку библиотека A открыла тип библиотеки B через собственный публичный API. То есть Node публично реализует INode<T>, что делает этот тип видимым для основной программы.

Обычно правильное решение - просто добавить ссылку на библиотеку B в основную программу. В конце концов, основной программе, безусловно, понадобится библиотека B во время выполнения, даже если она сама не имеет прямого доступа ни к одному из типов, объявленных в этой библиотеке.

Но есть альтернатива, если по какой-то причине добавление этой ссылки проблематично, при условии, что вы, по крайней мере, можете изменить Библиотеку А. То есть инкапсулировать использование типов из Библиотеки B, чтобы они не были видимый для кода, использующего библиотеку А. Как правило, эта инкапсуляция будет включать в себя некоторый вид прокси или оболочки, чтобы скрыть использование третьей библиотеки и (в некоторых случаях) раскрыть возможности третьей библиотеки для сборки, ссылающейся на вторую библиотека.

Например, вы можете изменить библиотеку A, чтобы она выглядела следующим образом:

namespace TopologyDAL
{
    public partial class Node
    {
        // Auto generated from EF
    }

    public partial class Node
    {
        public int Key { ... }

        private class NodeProxy : INode<int>
        {
            private readonly Node _node;

            public NodeProxy(Node node)
            {
                _node = node;
            }

            public int Key { get { return _node.Key; } }
        }

        private readonly NodeProxy _nodeProxy;

        public Node()
        {
            _nodeProxy = new NodeProxy(this);
        }
    }
}

Тогда везде, где вы хотите использовать метод расширения из библиотеки B, вы просто используете член _nodeProxy вместо this.

Конечно, вышеизложенное предполагает, что основная программа фактически не использует ничего непосредственно из Библиотеки B, и что все типы использования из Библиотеки B находятся только в Библиотеке A, и даже не возвращаются из Библиотеки A в возвращаемых значениях , типы собственности и т. д. Но что, если это не так? Что если, например, вы хотите, чтобы основная программа имела доступ к методу расширения из библиотеки B без ссылки на эту библиотеку?

Ну, мой первый ответ был бы "просто иди и уже ссылайся на сборку!" :) Но ради аргумента, скажем, вы не можете сделать это по какой-то причине, или, по крайней мере, это очень неудобно. Затем вы можете расширить прокси-подход, добавив прокси-методы в ваш тип библиотеки A, которые в свою очередь делегируют реализацию в библиотеке B.

Расширяя приведенное выше, например, можно добавить к объявлению класса Node другой метод:

public void FromNodeMixin()
{
    _nodeProxy.FromNodeMixin();
}

Обратите внимание, что сам метод не добавляет общедоступных случаев использования библиотеки B. Вместо этого он использует (ранее объясненный) экземпляр прокси-сервера для делегирования вызова методу расширения, объявленному в библиотеке B. Таким образом, фактически только библиотека A должна иметь ссылку на библиотеку B; основная программа может ссылаться на библиотеку A, не подвергаясь воздействию каких-либо типов в библиотеке B, и поэтому не нуждается в явной ссылке.


Теперь, все сказанное, я повторю, что - это на самом деле значение в , а не , работающее вокруг этой проблемы. Во-первых, добавление прокси может занять много времени. Это хорошо только для одного или двух типов, возможно, с несколькими методами. Но это станет очень быстро, если вы попытаетесь скрыть каждое косвенное использование библиотек DLL, от которых в противном случае вы использовали бы большое количество функций.

Также, как я уже упоминал ранее, отсутствие добавления ссылки на библиотеку B, конечно, не означает, что библиотека B не обязательно должна быть присутствующей для запуска программы. Вам по-прежнему необходимо иметь библиотеку, чтобы, если и когда библиотека A вызывала ее, ее можно было использовать. И наличие основной справочной программы Library B - один из самых простых способов, которые я знаю, чтобы убедиться, что Library B скопирована в выходной каталог сборки, чтобы убедиться, что DLL там.

0 голосов
/ 21 мая 2010

Все, что вы используете - это класс Node из библиотеки A, это правда.Однако частью определения класса Node является тот факт, что он реализует интерфейс INode<int> из библиотеки B.

Сам факт существования класса Node требует, чтобы вы включилиссылка на библиотеку Б.

0 голосов
/ 21 мая 2010

Частичный класс в c # - это просто класс, который существует в нескольких файлах. У вас не может быть двух файлов, которые определяют частичный класс в разных пространствах имен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...