2014-12-31 3 views
2

У меня возникли проблемы с поиском информации по этой теме, возможно, потому что я не уверен, как сформулировать вопрос. Надеюсь, здесь можно помочь или хотя бы посоветоваться. Эта ситуация может быть только тем, что я сохраняю, но это подталкивает меня, поэтому я подумал, что попрошу о помощи в том, как обойти это.Библиотека требует ссылки на System.Windows.Forms

У меня есть библиотека C#, заполненная служебными классами, используемыми в других сборках. Все мои расширения находятся в этой библиотеке, и это очень удобно. Любые другие библиотеки или исполняемые файлы, которые должны использовать эти классы, должны, естественно, ссылаться на библиотеку.

Но у одного из расширений, которые у меня есть, есть расширение в классе Control, чтобы обрабатывать обновления управления поточной передачей менее запутанно. Как следствие, библиотека утилиты должна ссылаться на System.Windows.Forms.

Проблема в том, что любая библиотека или исполняемый файл, который ссылается на библиотеку утилит, теперь должен иметь ссылку на System.Windows.Forms, либо я получаю ошибку сборки для отсутствующей ссылки. Хотя это не имеет большого значения, кажется, что глупо иметь сборки, которые не имеют ничего общего с элементами управления или формами, которые должны ссылаться на System.Windows.Forms только потому, что библиотека утилит делает особенно, поскольку большинство из них фактически не используют Расширение InvokeAsRequired(), которое я написал.

Я думал о перемещении расширения InvokeAsRequired() в его собственную библиотеку, что позволило бы устранить проблему System.Windows.forms, поскольку только сборки, которые должны были использовать расширение InvokeAsRequired(), уже имели бы ссылку на SWF ... но тогда у меня будет библиотека, в которой есть только одна вещь, которая, вероятно, будет беспокоить меня больше.

Есть ли способ обойти это требование, не отделяя метод «оскорбления» и создавая почти пустую библиотеку? Может быть, компиляция или что-то еще?

  • Следует отметить, что «метод нарушения» фактически используется для нескольких проектов, имеющих пользовательский интерфейс. Множество обновлений пользовательского интерфейса, которые я делаю, происходит в результате появления событий и попытки обновить элементы управления формой Windows из другого потока, вызвавшего различные проблемы с пользовательским интерфейсом. Следовательно, метод обработки Invoke при необходимости. (Хотя лично я думаю, что весь шаблон InvokeRequired должен быть завернут в сам элемент управления, а не иметь что-то внешнее, чтобы выравнивание потока в первую очередь).
+2

Ну, хорошо, это не принадлежит в библиотеке. Вы должны сделать все возможное, чтобы полностью избавиться от него. –

+0

См. [Это] (http://stackoverflow.com/a/16364022/643085). Это WPF, но вы можете применить тот же шаблон к приложению winforms. Кстати, да, пожалуйста, немедленно отмените весь свой код от winforms, так как он полностью устарел и бесполезен, и он даже не будет частью будущего .Net –

+6

«он даже не будет частью будущего .Net» - цитируйте, пожалуйста. Официальное заявление Microsoft не было, и это можно было бы толковать в поддержку этой претензии. –

ответ

2

Если это всего лишь одна функция, то упакуйте ее как файл исходного кода в пакет NuGet, а затем добавьте пакет NuGet в свои проекты. Затем этот код легко развертывается в новых проектах (а также легко обновляется), но вам не нужно создавать отдельную сборку. Просто скомпилируйте его в свое приложение.

Затем вы сохранили бы свой пакет NuGet в локальном репозитории NuGet или получили бы учетную запись myget или даже просто сохранили ее где-то в вашей сети. В худшем случае вы можете проверить его в своем управлении версиями, но я просто хочу проверить «проект», из которого вы создаете пакет nuget, поэтому при необходимости можете перестроить пакет.

Кто знает, в какой-то момент вы можете добавить дополнительные служебные функции, которые требуют оконных форм, и в этот момент вы можете оправдать отдельную сборку.

0

Это очень легко: у вас есть, чтобы переместить код нарушителя. На данный момент это может быть немного опасно, но, в конце концов, это может быть взрыв, который вы сделали сейчас, а не в тот момент, когда вы вынуждены.

Даже если это всего лишь один метод (пока), просто переместите метод в другую сборку.Я не сказал нового, это может быть в сборке, которая использует его, если из него вытекает только одна или все другие, которые нуждаются в этом моменте.

+0

Похоже, что консенсус «просто переместите его и сделайте с ним». работает на меня. –

+0

Да. Это общая идея;) –

0

Вы можете решить вашу проблему, переключив код библиотеки утилиты с early-binding pattern to the late-binding pattern, когда дело доходит до типов, объявленных в пространстве имен System.Windows.Forms.

В этой статье показано, как сделать это короткий путь: Stack Overflow: C#.NET - Type.GetType(“System.Windows.Forms.Form”) returns null

И этот фрагмент кода показывает, как monoresgen инструмент из Mono Project (с открытым исходным кодом # и .NET реализации ECMA CLI, C) решает проблему с System.Windows.Forms зависимостей.

public const string AssemblySystem_Windows_Forms = "System.Windows.Forms, Version=" + FxVersion + ", Culture=neutral, PublicKeyToken=b77a5c561934e089"; 

// ... 

static Assembly swf; 
static Type resxr; 
static Type resxw; 

/* 
* We load the ResX format stuff on demand, since the classes are in 
* System.Windows.Forms (!!!) and we can't depend on that assembly in mono, yet. 
*/ 
static void LoadResX() { 
    if (swf != null) 
     return; 
    try { 
     swf = Assembly.Load(Consts.AssemblySystem_Windows_Forms); 
     resxr = swf.GetType("System.Resources.ResXResourceReader"); 
     resxw = swf.GetType("System.Resources.ResXResourceWriter"); 
    } catch (Exception e) { 
     throw new Exception ("Cannot load support for ResX format: " + e.Message); 
    } 
} 

// ... 

static IResourceReader GetReader (Stream stream, string name, bool useSourcePath) { 
    string format = Path.GetExtension (name); 
    switch (format.ToLower (System.Globalization.CultureInfo.InvariantCulture)) { 
    // ... 
    case ".resx": 
     LoadResX(); 
     IResourceReader reader = (IResourceReader) Activator.CreateInstance (
      resxr, new object[] {stream}); 
     if (useSourcePath) { // only possible on 2.0 profile, or higher 
      PropertyInfo p = reader.GetType().GetProperty ("BasePath", 
       BindingFlags.Public | BindingFlags.Instance); 
      if (p != null && p.CanWrite) { 
       p.SetValue (reader, Path.GetDirectoryName (name), null); 
      } 
     } 
     return reader; 
    // ... 
    } 
} 

Отрывок Источник: https://github.com/mono/mono/blob/mono-3.10.0/mcs/tools/resgen/monoresgen.cs#L30

Смежные вопросы