2015-05-16 4 views
9

Я преобразовал структуру (C#) в класс и должен пройти все виды использования этого типа, чтобы гарантировать, что нет нежелательных эффектов прежней неявной копии и теперь эталонных поведений ,Visual Studio: найти все ссылки определенного типа

Есть ли способ найти все ссылки, в которых используется этот конкретный тип?

Я попробовал Find all References по типу и получил все местоположения, в которых явно указано название типа, что является хорошим началом.

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

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

+2

Изменчивая 'структура' является ** плохой идеей **. – xanatos

+1

Если вы сделаете свою структуру неизменной, вам не придется беспокоиться ни о какой из этих проблем. См. Рекомендации по разработке структуры: https://msdn.microsoft.com/en-us/library/ms229031%28v=vs.110%29.aspx –

+0

Да, изменчивые структуры плохо, но удобны. Но ты прав. Теперь я должен столкнуться с последствиями;) – azt

ответ

5

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

Вы можете отметить [Obsolete] класс, все его свойства, все его методы. Тогда у вас будет предупреждение каждый раз, когда вы их используете.

Обратите внимание, что [Obsolete] "трюк" имеет некоторые ограничения:

[Obsolete] 
public class MyClass 
{ 
} 

public static void Test1(MyClass test2) // This line has a warning 
{ 
    var y = test2; // ***This line doesn't have a warning*** 
    MyClass z = test2; // This line has a warning 
} 

так же, как Find all References ...

Другое решение, основанное на FxCop/анализа кода в Visual Studio:

Это специальное правило, на основе инструкций http://blogs.msdn.com/b/codeanalysis/archive/2010/03/26/how-to-write-custom-static-code-analysis-rules-and-integrate-them-into-visual-studio-2010.aspx

пространству имен по умолчанию в ASSEM bly (вы можете установить в свойствах) должно быть MyCustomFxCopRules. Цель платформы x86.

using Microsoft.FxCop.Sdk; 

namespace MyCustomFxCopRules 
{ 
    public class StructAssignmentFinder : BaseIntrospectionRule 
    { 
     public StructAssignmentFinder() 
      : base("StructAssignmentFinder", "MyCustomFxCopRules.RuleMetadata", typeof(StructAssignmentFinder).Assembly) 
     { 
      var ms = new MyStruct(); 
      var tt = ms; 
     } 

     public override TargetVisibilities TargetVisibility 
     { 
      get 
      { 
       return TargetVisibilities.All; 
      } 
     } 

     public override ProblemCollection Check(ModuleNode module) 
     { 
      Visit(module); 
      return Problems; 
     } 

public override void VisitAssignmentStatement(AssignmentStatement assignment) 
{ 
    // You could even use FullName 
    if ((assignment.Source != null && assignment.Source.Type != null && assignment.Source.Type.Name.Name == "MyStruct") || 
     (assignment.Target != null && assignment.Target.Type != null && assignment.Target.Type.Name.Name == "MyStruct")) 
    { 
     Problem problem = new Problem(GetNamedResolution("Struct", assignment.Target.Type.Name.Name), assignment); 
     Problems.Add(problem); 
    } 

    base.VisitAssignmentStatement(assignment); 
} 

public override void VisitConstruct(Construct construct) 
{ 
    Method targetMethod = (Method)((MemberBinding)construct.Constructor).BoundMember; 

    if (targetMethod.Parameters.Any(x => x.Type.Name.Name == "MyStruct")) 
    { 
     Problem problem = new Problem(GetNamedResolution("ParameterType", "MyStruct", targetMethod.Name.Name), construct); 
     Problems.Add(problem); 
    } 

    base.VisitConstruct(construct); 
} 

public override void VisitMethodCall(MethodCall call) 
{ 
    Method targetMethod = (Method)((MemberBinding)call.Callee).BoundMember; 

    if (targetMethod.ReturnType.Name.Name == "MyStruct") 
    { 
     Problem problem = new Problem(GetNamedResolution("ReturnType", targetMethod.ReturnType.Name.Name, targetMethod.Name.Name), call); 
     Problems.Add(problem); 
    } 

    if (targetMethod.Parameters.Any(x => x.Type.Name.Name == "MyStruct")) 
    { 
     Problem problem = new Problem(GetNamedResolution("ParameterType", "MyStruct", targetMethod.Name.Name), call); 
     Problems.Add(problem); 
    } 

    base.VisitMethodCall(call); 
} 

RuleMetadata.xml (он должен быть внедренный ресурс)

<?xml version="1.0" encoding="utf-8" ?> 
<Rules FriendlyName="Rules about Structs"> 
    <Rule TypeName="StructAssignmentRule" Category="MyRules" CheckId="CR1000"> 
    <Name>Struct Assignment Finder</Name> 
    <Description>Struct Assignment Finder</Description> 
    <Url></Url> 
    <Resolution Name="Struct">There is an assignment of struct '{0}'.</Resolution> 
    <Resolution Name="ReturnType">'{0}' is the return type for a call to '{1}'.</Resolution> 
    <Resolution Name="ParameterType">'{0}' is a parameter type for a call to '{1}'.</Resolution> 
    <Email></Email> 
    <MessageLevel Certainty="100">Warning</MessageLevel> 
    <FixCategories>NonBreaking</FixCategories> 
    <Owner></Owner> 
    </Rule> 
</Rules> 

Исходя из этого, тогда легко добавлять другие правила для других случаев угловыми, что я, конечно, забыл :-)

тестовый файл я использую:

public struct MyStruct 
{ 

} 

class Test 
{ 
    public Test() 
    { 
     var ms = new MyStruct(); 
     var ms2 = ms; 

     ms3 = ms; 
     ms = ms3; 

     ms4 = ms; 
     ms = ms4; 

     ms4 = ms4; 

     new MyObject(default(MyStruct)); 
    } 

    public MyStruct ms3; 
    public MyStruct ms4 { get; set; } 
} 

public class MyObject 
{ 
    public MyObject(MyStruct par1) 
    { 

    } 
} 

Обратите внимание, что отладка правил сложно ... это довольно легко отлаживать с помощью FxCopCmd.exe, но невозможно (я думаю, не уверен) отлаживать при вызове напрямую Visual Studio.

+0

Оба ваших замечания более или менее совпадают с поиском всех ссылок. Использовал трюк переименования, прежде чем VS представит эту функцию. Не знал трюк '[Устаревший]. В любом случае, прямо мне не поможет. – azt

+0

@azt С теоретической точки зрения, можно модифицировать IL-анализатор, чтобы найти все назначения ... В конце вам нужно найти все 'stloc' для вашего типа, все вызовы методов, которые имеют параметр ваш тип и т. д. ... – xanatos

+0

@azt можно использовать Code Analysis Visual Studio ... Вы должны написать собственное правило ... но довольно сложно отлаживать :-( – xanatos

1

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

+0

Он написал это в вопрос * Я попробовал ** Найти все Referenceson ** тип и получить все местоположения, в которых явно указано имя типа, что является хорошим началом. * – xanatos

+1

Найти все ссылки на тип - это одно. Оно укажет на каждый где имя типа указано явно. Найти все ссылки на, скажем, свойство класса, будет показывать все места, где это свойство было прочитано или написано, что не совпадает с тем, что описал ОП. –

+0

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

2

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

Вопрос заключался не столько в том, чтобы найти все виды использования, сколько в «проблемных», а именно в доступе к записи публичным пользователям. Вместо того, чтобы найти все ссылки на членов, как это предложено в this answer, я только хочу найти доступ на запись. Поэтому я использовал стратегию перезаписи, указанную в this answer, и заставлял всех участников писать только, поэтому компилятор будет жаловаться только на опасные записи для записи.

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

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

0

Если у вас установлено Visual Basic Web Essentials Extension, то это очень просто. Проверьте снимок экрана ниже. При нажатии на выделенную ссылку красным вы можете увидеть все ссылки определенного типа. enter image description here

+0

Вы уверены, что это не часть визуальной студии? – JavierIEH

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