Действительно ли возможно запросить пользовательские атрибуты в C# в течение времени компиляции (не время выполнения)

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

Напомним, у нас есть несколько инструментов ниже пояса:

  • Мы можем оптимально обрезать узлы с одним ребром, повторяя процесс до завершения

  • [113 ]

    Мы можем назначить направление любому ребру в простом цикле (связанные компоненты только с узлами степени 2), а остальные будут следовать (оптимально).

  • Узлы с двумя ребрами в более сложных циклах можно временно игнорировать, так как их направления ребер будут назначаться узлами более высокой степени.

После прочтения последнего пункта, сама проблема становится немного более понятной. После того, как мы удалили узлы степени один в пуле один, все остальные узлы имеют как минимум два ребра. Мы можем с уверенностью сказать в оптимальном графе, что каждый из этих узлов будет иметь хотя бы одно направленное ребро, указывающее на них. В качестве доказательства, поскольку каждый узел имеет по крайней мере два ребра, но связанный компонент не является простым циклом (иначе это будет исключено в пуле 2), у нас больше ребер, чем узлов. Если какой-либо узел имеет нулевые ребра, направленные к нему, один из этих ребер может быть обращен вспять, чтобы уменьшить количество конфликтующих ребер или «освободить» другой узел, чтобы иметь нулевые внутренние ребра, чтобы затем сделать то же самое.

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

Первоначально я пытался составить алгоритм, основанный на пуле три, для выполнения этого задания, но оказалось, что ответ на самом деле намного проще, чем даже. Единственный способ, которым мы можем случайно создать узел без ребер, направленных от него, - это активное направление всех ребер от этого узла. Решение состоит в том, чтобы выбрать одно ребро в подключенном компоненте и назначить ему случайное направление. Затем выполните поиск (DFS, BFS и т. Д.) Вне узла, на который он направлен, назначая направления ребрам по ходу движения в том направлении, в котором вы их проходите. Любой узел, к которому вы достигнете, будет иметь ребро, направленное на него (ребро, которое вы использовали для его достижения), а корневой узел имеет ребро, которое вы ему назначили вручную.

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

21
задан 5 revs 23 May 2017 в 10:29
поделиться

6 ответов

Нет, зацепить компиляцию невозможно сборки и проверьте, существует ли она.

Однако вы можете подключиться к процессу сборки, который состоит не только из запуска компилятора. Вы можете создать пользовательскую задачу MSBUILD (или NAnt, если вы ее используете), которая проверяет сборку через отражение после ее построения и затем завершает сборку, если у нее нет требуемых атрибутов.

Конечно, вам следует вероятно, еще проверит это и в коде. То, что вы пытаетесь сделать, не является хорошей заменой для правильной проверки во время выполнения.

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

Однако вы можете подключиться к процессу сборки, который состоит не только из запуска компилятора. Вы можете создать пользовательскую задачу MSBUILD (или NAnt, если вы ее используете), которая проверяет сборку через отражение после ее построения и затем завершает сборку, если у нее нет требуемых атрибутов.

Конечно, вам следует вероятно, еще проверит это и в коде. То, что вы пытаетесь сделать, не является хорошей заменой для правильной проверки во время выполнения.

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

Однако вы можете подключиться к процессу сборки, который состоит не только из запуска компилятора. Вы можете создать пользовательскую задачу MSBUILD (или NAnt, если вы ее используете), которая проверяет сборку через отражение после ее построения и затем завершает сборку, если у нее нет требуемых атрибутов.

Конечно, вам следует вероятно, еще проверит это и в коде. То, что вы пытаетесь сделать, не является хорошей заменой для правильной проверки во время выполнения.

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

Конечно, вам, вероятно, все же нужно проверить это в код также. То, что вы пытаетесь сделать, не является хорошей заменой для правильной проверки во время выполнения.

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

Конечно, вам, вероятно, все же нужно проверить это в код также. То, что вы пытаетесь сделать, не является хорошей заменой для правильной проверки во время выполнения.

7
ответ дан 29 November 2019 в 22:06
поделиться

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

Вам придется написать приложение командной строки, которое загружает DLL и отражает типы. Затем вы запускаете это приложение командной строки как шаг после сборки. Я делал это в прошлом. Это не очень сложно сделать, если вы понимаете API отражения.

PostSharp делает это для достижения аспектно-ориентированного программирования. Довольно круто, на самом деле.

4
ответ дан 29 November 2019 в 22:06
поделиться

Атрибуты только во время выполнения. Однако:

Было бы возможно создать правило в FXCop (статический анализ), которое не будет выполнено, если атрибут не определен, и ваш процесс сборки / регистрации может проверить это правило и произойдет сбой соответствующим образом.

1
ответ дан 29 November 2019 в 22:06
поделиться

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

1
ответ дан 29 November 2019 в 22:06
поделиться

Для меня это больше похоже на проблему тестирования, чем на проблема компиляции. То есть вы спрашиваете "откуда мне знать, что мой код написан правильно?" где «написано правильно» имеет (среди прочего) значение, что все классы украшены определенным атрибутом. Я бы подумал о написании модульных тестов, которые проверят, что ваши правила включения атрибутов действительно соблюдаются. Вы можете сделать так, чтобы процесс сборки (и / или регистрации) выполнял этот конкретный набор тестов после сборки (перед проверкой) как условие успешной сборки (регистрации). Он не прервет компиляцию, поскольку для выполнения тестов он должен быть завершен, но, так сказать, он нарушит сборку.

1
ответ дан 29 November 2019 в 22:06
поделиться
//PLEASE COMMENT IF YOU FIND BUGS OR SUGGEST IMPROVEMENTS


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MustHaveAttributes
{
 [AttributeClass ( "Yordan Georgiev", "1.0.0" )] 
 class Program
 {


 static void Main ( string [] args )
 {
  bool flagFoundCustomAttrOfTypeAttributeClass = false; 
  Console.WriteLine ( " START " );

  // what is in the assembly
  Assembly a = Assembly.Load ( "MustHaveAttributes" );
  Type[] types = a.GetTypes ();
  foreach (Type t in types)
  {
   object[] arrCustomAttributes = t.GetCustomAttributes ( true );


   if (arrCustomAttributes == null || arrCustomAttributes.GetLength ( 0 ) == 0)
   {
    //DO NOT CHECK IN
    ExitProgram ( t, "Found class without CustomAttributes" );
   }


   foreach (object objCustomAttribute in arrCustomAttributes)
   {
    Console.WriteLine ( "CustomAttribute for type  is {0}", t );
    if (objCustomAttribute is AttributeClass)
     flagFoundCustomAttrOfTypeAttributeClass = true; 
   }

   if (flagFoundCustomAttrOfTypeAttributeClass == false)
   { //DO NOT CHECK IN 
    ExitProgram ( t, "Did not found custom attribute of type AttributeClass" );
   }
   Console.WriteLine ( "Type is {0}", t );
  }
  Console.WriteLine ("{0} types found", types.Length );

  //NOW REQUIREMENTS IS PASSED CHECK IN
  Console.WriteLine ( " HIT A KEY TO EXIT " );
  Console.ReadLine ();
  Console.WriteLine ( " END " );
 }



 static void ExitProgram ( Type t, string strExitMsg  )
 {

  Console.WriteLine ( strExitMsg );
  Console.WriteLine ( "Type is {0}", t );
  Console.WriteLine ( " HIT A KEY TO EXIT " );
  Console.ReadLine ();

  System.Environment.Exit ( 1 );

 }
} //eof Program


//This will fail even to compile since the constructor requires two params
//[AttributeClass("OnlyAuthor")]  
//class ClassOne
//{ 

//} //eof class 


////this will not check in since this class does not have required custom
////attribute
//class ClassWithoutAttrbute
//{ }



[AttributeClass("another author name " , "another version")]
class ClassTwo
{ 

} //eof class


[System.AttributeUsage ( System.AttributeTargets.Class |
 System.AttributeTargets.Struct, AllowMultiple = true )]
public class AttributeClass : System.Attribute
{

 public string MustHaveDescription { get; set; }
 public string MusHaveVersion { get; set; }


 public AttributeClass ( string mustHaveDescription, string mustHaveVersion )
 {
  MustHaveDescription = mustHaveDescription;
  MusHaveVersion = mustHaveVersion;
 }

} //eof class 

} // пространство имен eof

0
ответ дан 29 November 2019 в 22:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: