I have a background in C++ and recently I started working in C#.
I have written following pieces of code (in Visual Studio):
var list_Loads = database.GetData<Load>().ToList();
var test_list = list_Loads.Where(o => (o.Name.Substring(0, 3) == "123")).ToList();
When I run the program and I move my mouse over both lists, first I get the count, which is very useful, but when I ask for the entries, this is what I get:
0 : namespace.Load
1 : namespace.Load
2 : namespace.Load
...
Not very useful, as you can imagine :-)
So my question: how can I show the Name attributes of those objects?
I thought: no problem. I have a background in native visualisers, so it should be rather easy to turn this into useful information, but then it comes:
In order to alter the way that those objects are represented, there is the first proposal to add a [DebuggerDisplay] "tag" to the definition of that class in source code.
However, as those classes are part of a framework I'm just referring to, I don't have access to the source code and hence I can't modify this.
Then I found another solution, which comes down to: "Write an entire C# project, debug, test and install it and it might work" (see documentation on "Custom visualisers of data" on the Microsoft website).
I almost choked in my coffee: writing an entire project, just for altering the view of an object??? (While, in C++, you just create a simple .natvis file, mention the classname and some configuration, launch .nvload and that's it.
Does anybody know a simple way to alter the appearance of C# object, without needing to pass through the whole burden of creating an entire C# project?
By the way, when I try to load a natvis file in Visual Studio immediate window, this is what I get:
.nvload "C:\Temp_Folder\test.natvis"
error CS1525: Invalid expression term '.'
What am I doing wrong?
Thanks in advance
OP (my emphasis):
In order to alter the way that those objects are represented, there is the first proposal to add a [DebuggerDisplay] "tag" to the definition of that class in source code.
However, as those classes are part of a framework I'm just referring to, I don't have access to the source code and hence I can't modify this.
Does anybody know a simple way to alter the appearance of C# object, without needing to pass through the whole burden of creating an entire C# project?
If you just want to specify [DebuggerDisplay] on a type, you don't have to have access to the source code. You can make use of [assembly:DebuggerDisplay()] and control how a type appears in the debugger. The only downside is that [assembly:DebuggerDisplay()] naturally only affects the current assembly whose code your mouse is hovering over. If you wish to use the customised display in other assemblies that you own, then you must repeat the [assembly:DebuggerDisplay()] definition.
Here's an easy before-and-after example with DateTime. I picked DateTime because we generally don't have access to the source code and it has some interesting properties:
var items = new List<DateTime>
{
DateTime.Now.AddDays(-2),
DateTime.Now.AddDays(-1),
DateTime.Now
};
...which on my machine defaults to:
Maybe I'm fussy and I just want to see:
Day of the week and
Day of the year
...I can do that via:
using System.Diagnostics;
[assembly: DebuggerDisplay("{DayOfWeek} {DayOfYear}", Target = typeof(DateTime))]
...which results in:
Example:
namespace DebuggerDisplayTests
{
public class DebuggerDisplayTests
{
public DebuggerDisplayTests()
{
var items = new List<DateTime>
{
DateTime.Now.AddDays(-2),
DateTime.Now.AddDays(-1),
DateTime.Now
};
}
}
.
.
.
}
Overrides
[assembly:DebuggerDisplay()] can also be used as a means to override pre-existing [DebuggerDisplay] on a 3-rd party type. Don't like what style they have chosen? Is the type showing far too much information? Change it with [assembly:DebuggerDisplay()].
Related
We have some guidelines, how we want to use our namespaces and there are also access restrictions on them. Because developers are doing this wrong sometimes, we need to analyze these rules. Currently we are doing this with nDepend, which is working good. But the process that someone have to overwatch this, go to the guy who violated these rules and force him to fix it, is very time consuming. So it would be very nice to get instant notice while developing, or at least after building the current changes. This should be a job for a roslyn analyzer.
I've introduced myself into roslyn the past 3 hours, but I'm a bit overwhelmed with the feature list and how they work. Maybe you can give me a hint, how I could achieve what I want.
We are talking about a solution with >1m lines of code and nearly 35000 types. So peformance does matter a lot.
What I want to do:
get the current class
get the namespace of the current class
get all used types with their full name
If I'm able to do this, the rest would be relatively easy. I've played arround with it and maybe I need the current project of the opened class and the compilation. But opening this is very time consuming and therefore the performance would be very ugly.
A Roslyn analyzer can register a bunch of different code actions, eg. on the "whole file" level, the method, every single syntax node, or symbol. Depending on what you're exactly are trying to analyze, any of those might be applicable for you. Especially, as you indicate, you're concerned about performance. See the AnalysisContext.Register*Action() methods, for possible "hooks" you can add.
To get the things that you want:
1 Get the current class
Basically, with any of those, you should be able to get the current class (if registering syntax node or symbol action), or all declared classes (for example, with registering a compilation action, or syntax tree action). But the most simple option is to register a syntax node analysis for class nodes, you can do that like this:
context.RegisterSyntaxNodeAction(AnalyzeClassNode, SyntaxKind.ClassDeclaration);
Where AnalyzeClassNode is an action to analyze the class declaration. That will receive an additional context (a SyntaxNodeAnalysisContext), which contains the class declaration syntax node.
2 Get the namespace of the current class
For this, you need the semantic model. Let's say you used the RegisterSyntaxNodeAction method, and declared a method AnalyzeClassNode, then in the body, you can do this:
var classNode = context.Node;
var model = context.SemanticModel;
var classSymbol = model.GetDeclaredSymbol(classNode);
And you get the namespace symbol with:
var #namespace = classSymbol.ContainingNamespace;
And .MetadataName will give you the namespace as string.
3 Get all used types with their full name
That's something much more complex, and really depends on what you're trying to achieve here. To really get to something like "all dependent types, or imports". You should traverse the entire class node, get the symbol for every useful node (I have no idea what that would entail), and checking it's namespace, or full metadata name.
Maybe, you can elaborate a little bit more on this, to find out if this is the right approach.
By the way, check out "Learn Roslyn Now", a site with a bunch of tutorials for Roslyn. Specifically, you want to checkout part 3 (for syntax nodes), 7 (for symbols), and 10 (intro to analyzers).
I'm currently working on a dll which would be used across future projects, and trying to fill it with every useful method developped in the last one. One of these methods that i'd like to re-use allows to generate an excel file with any object collection, and uses a resx resource file to get the column headers based on the object's property names.
Now, my problem is that I can't access or even check the existence of such a file from the library. A possible workaround would be to turn this resource file into a dictionary and pass it as a parameter, but I didn't find a way to do so or any documentation on the subject. Any hint or suggestion about this ?
Thank you for helping me here...
P.S. : I'm working with Visual Studio 2013, in case that could be relevant.
Here's a workaround I found and which allows to get a "RuntimeResourceSet" object, which is structurally close to a dictionnary (and which could be easily turned into one, if you specifically need a dictionnary) :
var myResourceSet = MyResource.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true);
Then, you can get the set's items this way :
var myString = myResourceSet.GetString("MyKey");
Hope that will help !
I am using 2 separators, and I re-create the dictionary by using split:
Dictionary<string, string> MyDictionary = Resource.MyResourceNme.Split(',').ToDictionary(x => x.Split('|')[0], x => x.Split('|')[1]);
MyResource would look like:
AUD|SYD,GBP|LON,JPY|TOK
Maybe there is a more efficient way of doing it (I don't like using twice the second split).
I am learning how to use the Telerik test environment.
I created a test that runs through my program. One of the steps is to create a repository, into which I will upload data. I would like to run this test numerous times as a load test, so the name needs to be dynamic. I would like to create a name such as "Repository_Date_Time, since no matter how many times I use it, uniqueness is guaranteed.
I created a code step right before the text box insertion step. I would like to generate a string, and then use it in the next step so that the repository is created with a unique name.
Code generated is: this is in the steps within the telerik application
[WebTest_CodedStep] : New Coded Step
Then, within this step, I can hard code stuff:
[CodedStep(#"New Coded Step")]
public void WebTest_CodedStep()
{
}
I want to use something like this: string currentTime = DateTime.Now.ToString("HH:mm:ss");
and then use the saveNow contained data as an ending to a string to make it unique, but it must be done within the following step:
Type 'Moshe-Master Repository Test01' into Item0Textboxchanged
TypedText: Moshe-Master Repository Test01
So that the red name will be substituted by a variable carrying the new string which I creatred.
The TypedText box is the value being typed automatically, and I would like to change it with the generated value from the previous step. Can a TypedText value be dynamic?
Thanks!
EDIT: I just realized that therre is a way to use a variable as input, however, I do not know where I can create it. The location where I can put it as input is in the top right state-chart with all current data being used for that particular step. (bindings) is set to collection at the moment. When I try to change it into a variable it tells me that the variable needs to be created- it does not specify where.
I am trying to get started in Visual Studio (2010) extensions and I am having a hard time finding the right materials. I have the SDK, but the included samples seem to be things like adorners, windows, and icons.
I am trying to make an extension that will work directly with the text editor (to alphabetize all of my method names in a class, or make all constant names upper case for example) but I can't find a demo for this type of functionality, or even a tutorial.
Does anyone know where I can find this kind of stuff?
I had the exact same question and now have browsed the web several hours until I was being able to understand and explain how you'd need to start with such an extension.
In my following example we will create a small and dumb extension which will always add "Hello" to the beginning of a code file when an edit has been made. It's very basic but should give you an idea how to continue developing this thing.
Be warned: You have to parse the code files completely on your own - Visual Studio does not give you any information about where classes, methods or whatever are and what they contain. That's the biggest hurdle to be taken when doing a code formatting tool and will not be covered in this answer.[*]
For those who skipped to this answer, make sure you downloaded and installed the Visual Studio SDK first or you will not find the project type mentioned in step one.
Creating the project
Start by creating a new project of the type "Visual C# > Extensibility > VSIX Project" (only visible if you selected .NET Framework 4 as the target framework). Please note that you may have to select the "Editor Classifier" project type instead of the "VSIX Project" type to get it working, s. comment below.
After the project has been created, the "source.extension.vsixmanifest" file will be opened, giving you the ability to set up product name, author, version, description, icon and so on. I think this step is pretty self-explaining, you can close the tab now and restore it later by opening the vsixmanifest file.
Creating a listener class to get notified about text editor instance creations
Next, we need to listen whenever a text editor has been created in Visual Studio and bind our code formatting tool to it. A text editor in VS2010 is an instance of IWpfTextView.
Add a new class to our project and name it TextViewCreationListener. This class has to implement the Microsoft.VisualStudio.Text.Editor.IWpfTextViewCreationListener interface. You need to add a reference to Microsoft.VisualStudio.Text.UI.Wpf to your project. The assembly DLL is found in your Visual Studio SDK directory under VisualStudioIntegration\Common\Assemblies\v4.0.
You have to implement the TextViewCreated method of the interface. This method has a parameter specifying the instance of the text editor which has been created. We will create a new code formatting class which this instance is passed to later on.
We need to make the TextViewCreationListener class visible to Visual Studio by specifying the attribute [Export(typeof(IWpfTextViewCreationListener))]. Add a reference to System.ComponentModel.Composition to your project for the Export attribute.
Additionally, we need to specify with which types of files the code formatter should be bound to the text editor. We only like to format code files and not plain text files, so we add the attribute [ContentType("code")] to the listener class. You have to add a reference to Microsoft.VisualStudio.CoreUtility to your project for this.
Also, we only want to change editable code and not the colors or adornments around it (as seen in the example projects), so we add the attribute [TextViewRole(PredefinedTextViewRoles.Editable)] to the class. Again you need a new reference, this time to Microsoft.VisualStudio.Text.UI.
Mark the class as internal sealed. At least that's my recommendation. Now your class should look similar to this:
[ContentType("code")]
[Export(typeof(IWpfTextViewCreationListener))]
[TextViewRole(PredefinedTextViewRoles.Editable)]
internal sealed class TextViewCreationListener : IWpfTextViewCreationListener
{
public void TextViewCreated(IWpfTextView textView)
{
}
}
Creating a class for code formatting
Next, we need a class handling the code formatting logic, sorting methods and so on. Again, in this example it will simply add "Hello" to the start of the file whenever an edit has been made.
Add a new class called Formatter to your project.
Add a constructor which takes one IWpfTextView argument. Remember that we wanted to pass the created editor instance to this formatting class in the TextViewCreated method of our listener class (simply add new Formatter(textView); to the method there).
Save the passed instance in a member variable. It'll become handy when formatting the code later on (e.g. for retrieving the caret position). Also tie up the Changed and PostChanged events of the TextBuffer property of the editor instance:
public Formatter(IWpfTextView view)
{
_view = view;
_view.TextBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(TextBuffer_Changed);
_view.TextBuffer.PostChanged += new EventHandler(TextBuffer_PostChanged);
}
The Changed event is called every time an edit has been made (e.g. typing a char, pasting code or programmatical changes). Because it also reacts on programmatical changes I use a bool determining if our extension or the user / anything else is changing the code at the moment and call my custom FormatCode() method only if our extension is not already editing. Otherwise you'll recursively call this method which would crash Visual Studio:
private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
{
if (!_isChangingText)
{
_isChangingText = true;
FormatCode(e);
}
}
We have to reset this bool member variable in the PostChanged event handler again to false.
Let's pass the event args of the Changed event to our custom FormatCode method because they contain what has changed between the last edit and now. Those edits are stored in the array e.Changes of the type INormalizedTextChangeCollection (s. the link at the end of my post for more information about this type). We loop through all those edits and call our custom HandleChange method with the new text which this edit has produced.
private void FormatCode(TextContentChangedEventArgs e)
{
if (e.Changes != null)
{
for (int i = 0; i < e.Changes.Count; i++)
{
HandleChange(e.Changes[0].NewText);
}
}
}
In the HandleChange method we could actually scan for keywords to handle those in a specific way (remember, you have to parse any code on yourself!) - but here we just dumbly add "Hello" to the start of the file for testing purposes. E.g. we have to change the TextBuffer of our editor instance. To do so, we need to create an ITextEdit object with which we can manipulate text and apply it's changes afterwards. The code is pretty self-explaining:
private void HandleChange(string newText)
{
ITextEdit edit = _view.TextBuffer.CreateEdit();
edit.Insert(0, "Hello");
edit.Apply();
}
When compiling this add-in, an experimental hive of Visual Studio starts up with only our extension loaded. Create a new C# file and start typing to see the results.
I hope this gives you some ideas how to continue in this topic. I have to explore it myself now.
I highly recommend the documentation of the text model of the editor on MSDN to get hints about how you could do this and that.
http://msdn.microsoft.com/en-us/library/dd885240.aspx#textmodel
Footnotes
[*] Note that Visual Studio 2015 or newer come with the Rosyln Compiler Platform, which indeed already analyzes C# and VB.NET files for you (and probably other pre-installed languages too) and exposes their hierarchical syntactical structure, but I'm not an expert in this topic yet to give an answer on how to use these new services. The basic progress of starting an editor extension stays the same as described in this answer anyway. Be aware that - if you use these services - you will become dependent on Visual Studio 2015+, and the extension will not work in earlier versions.
just have a look at the "Getting started with Editor extensions" site on the MSDN http://msdn.microsoft.com/en-us/library/dd885122.aspx
Thorsten
I have seen the following code:
[DefaultValue(100)]
[Description("Some descriptive field here")]
public int MyProperty{...}
The functionality from the above snippit seems clear enough, I have no idea as to how I can use it to do useful things. Im not even sure as to what name to give it!
Does anyone know where I can find more information/a tutorial on these property attributes?
I would be also interested in any novel / useful tasks this feature can do.
The functionality from the above
snippit seems clear enough,
Maybe not, as many people think that [DefaultValue()] sets the value of the property. Actually, all it does to tell some visual designer (e.g. Visual Studio), what the code is going to set the default value to. That way it knows to bold the value in the Property Window if it's set to something else.
People have already covered the UI aspect - attributes have other uses, though... for example, they are used extensively in most serialization frameworks.
Some attributes are given special treatment by the compiler - for example, [PrincipalPermission(...)] adds declarative security to a method, allowing you to (automatically) check that the user has suitable access.
To add your own special handling, you can use PostSharp; there are many great examples of using PostSharp to do AOP things, like logging - or just code simplification, such as with automatic INotifyPropertyChanged implementation.
They are called Attributes, there is a lot of information in msdn, e.g. http://msdn.microsoft.com/en-us/library/z0w1kczw.aspx
In general they don't "do" anything on their own, they are used by some other code that will use your class. XmlSerialization is a good example: XmlSerializer (provided by Microsoft as part of the framework) can almost any class (there are a number of requirements on the class though) - it uses reflection to see what data is contained in the class. You can use attributes (defined together with XmlSerializer) to change the way XmlSerializer will serialize your class (e.g. tell it to save the data as attribute instead of an element).
The ones in your example is used by the visual designer (i.e. MS Expression Blend and Visual Studio designer) to give hints in the designer UI.
Note that they are metadata and will not affect the property logic. Setting DefaultValue for instance will not set the property to that value by default, you have to do that manually.
If you for some reason want to access these attributes, you would have to use reflection.
See MSDN for more information about designer attributes.
We use it to define which graphical designer should be loaded to configure
an instance of a specific type.
That is to say, we have a kind of workflow designer which loads all possible command
types from an assembly. These command types have properties that need to be configured,
so every command type has the need for a different designer (usercontrol).
For example, consider the following command type (called a composite in our solution)
[CompositeMetaData("Delay","Sets the delay between commands",1)]
[CompositeDesigner(typeof(DelayCompositeDesigner))]
public class DelayComposite : CompositeBase
{
// code here
}
This is information is used in two places
1) When the designer creates a list of commands, it uses the CompositeMetaData
to display more information about the command.
2) When the user adds a command to the designer and the designer creates
an instance of that class, it looks at the CompositeDesigner property,
creates a new instance of the specified type (usercontrol) and adds it
to the visual designer.
Consider the following code, we use to load the commands into our "toolbar":
foreach (Type t in assembly.GetExportedTypes())
{
Console.WriteLine(t.Name);
if (t.Name.EndsWith("Composite"))
{
var attributes = t.GetCustomAttributes(false);
ToolboxListItem item = new ToolboxListItem();
CompositeMetaDataAttribute meta = (CompositeMetaDataAttribute)attributes
.Where(a => a.GetType() == typeof(Vialis.LightLink.Attributes.CompositeMetaDataAttribute)).First();
item.Name = meta.DisplayName;
item.Description = meta.Description;
item.Length = meta.Length;
item.CompositType = t;
this.lstCommands.Items.Add(item);
}
}
As you can see, for every type in the assembly of which the name ends with "Composite",
we get the custom attributes and use that information to populate our ToolboxListItem instance.
As for loading the designer, the attribute is retreived like this:
var designerAttribute = (CompositeDesignerAttribute)item.CompositType.GetCustomAttributes(false)
.Where(a => a.GetType() == typeof(CompositeDesignerAttribute)).FirstOrDefault();
This is just one example of how you might be able to use custom attributes,
I hope this gives you a place to start.
These attributes customize the design time experience.
http://msdn.microsoft.com/en-us/library/a19191fh.aspx