I am having difficulty with Find All References feature in Visual Studio 2017 (and 2015 at least, may be older too).
I have this defined in one project (C#):
public static class AlgorithmNames
{
public static readonly string
FaceAnalyzerAlgorithm = "Face Analyzer Algorithm (C++)",
StaticFaceAnalyzerAlgorithm = "Static Face Analyzer Algorithm (C++)";
}
and it's used in another project (C++/CLI) in the same solution like so:
public ref class FaceAnalyzerAlgorithm : AlgorithmBase
{
public:
property String^ Name
{
String^ get() override { return AlgorithmNames::FaceAnalyzerAlgorithm; }
};
...
When I right click Find All References on the definition of FaceAnalyzerAlgorithm (C#) it does not find the use just the definition even though the filter says "Entire Solution".
When I right click Find All References on the use (C++/CLI) it finds nothing and nothing happens in UI to indicate any activity. Go To Definition and Go To Declaration both end up in Object Browser.
Issues like this do not seem to happen when it's just C#, but as soon as there is C++ it fails miserably. Any fixes or workarounds welcome.
Related
Imagine i have an extension method that operates of an interface of abstract objects:
public static void BlowTheirWhoHoovers(this ICollection<Image> source)
{
...
}
This extension knows how to blow the who hoovers of a list of images.
Note:
it's a list of Images, which is abstract. As long as the lists contain anything that descends from Image (e.g. Bitmap, Metafile, PngImage) the extension can handle it
source list can by any kind of list as long as it exposes ICollection
since source list is going to potentially have items added or removed, it is ICollection rather than IEnumeration (IEnumeration doesn't support modifying the list)
That's all well and good, except it doesn't work, the extension method is not found:
Collection<Bitmap> whoHonkers = new Collection<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();
i assume this fails because:
Visual Studio doesn't think Collection implements ICollection<T>
Visual Studio doesn't think Bitmap descends from Image
Now i can change my extension:
public static void BlowTheirWhoHoovers(this Collection<Bitmap> source)
{
...
}
which does compile:
except it's no longer useful (it requires Collection, and it requires Bitmap), e.g. it fails to work on anything except Collection<T>:
List<Bitmap> whoHonkers = new List<Bitmap>();
whoHonkers.BlowTheirWhoHoovers();
It also fails on anything that it's Bitmap:
List<Metafile> whoHonkers = new List<Metafile>();
whoHonkers.BlowTheirWhoHoovers();
or
List<PngImage> whoHonkers = new List<PngImage>();
whoHonkers.BlowTheirWhoHoovers();
How can i apply an extension to anything that is:
ICollection<Image>
?
i can't force anyone to change their declaration, e.g.:
List<Bitmap>
to
Collection<Image>
Update:
Possible avenues of solution exploration:
finding the syntax that allows extensions on things that the compiler should be able to do
manually casting the list; doing the compiler's job for it
Update#2:
i could have simplified some of the distractions around ICollection, and made it IEnumerable (since it's a hypothetical example i can make up whatever i want). But the screenshots already show Collection, so i'm going to leave it as it is.
Update#3:
As foson pointed out, changing it to IEnumerable allows a way to cheat the answer. So it definitely should stay as ICollection.
Sounds like a covarient problem.
If you change the signature to
public static void BlowTheirWhoHoovers(this IEnumerable<Image> source)
you should be able to do it in .NET 4 (not SL).
The problem with varience is that if you passed into the method an ICollection<JpegImage>, the method itself wouldn't know that it could only add JpegImages and not Bitmaps, defeating type saftey. Therefore the compiler does not let you do it. IEnumerable's type parameter is covarient, as seen by the out keyword, while ICollection's type parameter is not (since it is both in return positions and method parameter positions in the ICollection interface)
public interface IEnumerable<out T>
http://msdn.microsoft.com/en-us/library/dd799517.aspx
Doing a search around I've found this kind of question being asked in the past but not targeted at VS2010 or C# .Net 4. Has anyone come across a way to make interface comments inherit through to the implementation classes for intellisense to use?
A colleague suggested copy and paste into the implementation but there must be a better way. Looking at the previous question recommendations Sandcastle appears to be a documentation generator which isn't what I need.
Consider the following:
public interface IFoo
{
/// <summary>
/// Comment comment comment
/// </summary>
string Bar { get; set; }
}
public class Foo : IFoo
{
public string Bar { get; set; }
}
public class Test
{
public Test()
{
IFoo foo1 = new Foo();
foo1.Bar = "Intellisense comments work";
Foo foo2 = new Foo();
foo2.Bar = "Intellisense comments don't work";
}
}
Is there a way to make intellisense on foo2 work?
It can't be done automatically without changing the IntelliSense in VS.
A colleague of mine uses ReSharper (http://www.jetbrains.com/resharper/) and I asked him to try out your code - and it does do exactly what you're asking for as it extends the intellisense of VS. You might want to look into that.
However, for me the simplest way to achieve this is the free version of GhostDoc - http://submain.com/products/ghostdoc.aspx which makes bringing in the base documentation of a method/property a single key combination.
The downside being that it's cloning the documentation, therefore if that base documentation changes you have to remember to go and clear it on the derived class/interface and re-generate it.
The ReSharper solution, of course, does not suffer from this problem, so you pays your money (literally, in the case of ReSharper) and takes your choice. There might be other free plugins that achieve this, of course.
I trying to hook several Visual Studio events. Unfortunately I am failing in the first step. The event handlers are never called.
So my question is what I am doing wrong?
Here a little excerpt of my code.
// here are some attributes
[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)]
public sealed class VSPackage : Package {
EnvDTE80.DTE2 dte_;
EnvDTE.DocumentEvents documentEvents_;
EnvDTE.WindowEvents windowEvents_;
public VSPackage2Package() {
Trace.WriteLine("I am get called.");
}
protected override void Initialize() {
Trace.WriteLine("I am get called too.");
dte_ = (EnvDTE80.DTE2) System.Runtime.InteropServices.Marshal.
GetActiveObject("VisualStudio.DTE.10.0");
windowEvents_ = dte_.Events.WindowEvents;
documentEvents_ = dte_.Events.DocumentEvents;
windowEvents_.WindowCreated +=
new EnvDTE._dispWindowEvents_WindowCreatedEventHandler(
windowEvents_WindowCreated);
documentEvents_.DocumentOpened +=
new EnvDTE._dispDocumentEvents_DocumentOpenedEventHandler(
documentEvents__DocumentOpened);
Trace.WriteLine("Everything fine until here.");
}
void documentEvents__DocumentOpened(EnvDTE.Document document) {
Trace.WriteLine("Never called");
}
void windowEvents_WindowCreated(EnvDTE.Window window) {
Trace.WriteLine("Never called");
}
}
Edit:
I get it working, looking at other sample code, I figured out that they sometimes getting the DTE object differently. Changing
dte_ = (EnvDTE80.DTE2) System.Runtime.InteropServices.Marshal.
GetActiveObject("VisualStudio.DTE.10.0");
to
dte_ = GetService(typeof(EnvDTE.DTE)) as EnvDTE80.DTE2;
and now everything is fine.
It should work.
I'm pretty sure that if you do the same from an Addin it would work. Packages can be painfull sometimes.
In fact, when a package is loaded the shell (DTE) may not be fully loaded yet. Try to register your events when it is.
To do so, use the OnShellPropertyChange event and the Zombie state to know when to register.
http://social.msdn.microsoft.com/forums/en-US/vsx/thread/3097a0e1-68e3-47ea-a4ba-8511571b2487/
Read the following, I think it answers your question. Note : The GetService method is the same as calling GetGlobalService.
1. ServiceProvider.GlobalProvider
This new static property on the
ServiceProvider class allows access to
the global service provider from any
code, as long as it is called from the
main UI thread. This property is
closely related to the
Package.GetGlobalService static method
which was available in previous
versions of the MPF. The problem with
Package.GetGlobalService was that it
would fail if a package had not yet
been initialized. This led to subtle
ordering bugs in code that used the
MPF libraries without initializing a
package of their own. Sometimes they
would work only because another
package had already initialized the
global ServiceProvider on their
behalf. If that other package was
uninstalled, or perhaps moved to a
different version of the MPF, that
static would no longer be initialized
causing Package.GetGlobalService to
fail.
Now, in MPF 10, you can call
ServiceProvider.GlobalProvider at any
time as long as you are calling from
the UI thread. For compatibility, this
mechanism will still use the
ServiceProvider created by the first
Package to be sited but, in the case
where no Package has yet been
initialized, MPF 10.0 now has the
ability to obtain the global provider
from the registered COM message
filter. Package.GetGlobalService() is
also hooked up to this new mechanism.
Make sure you are not boxing and unboxing your DTE object. I found this was the issue for me.
See my solution here: http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/eb1e8fd1-32ad-498c-98e9-25ee3da71004
I'm making my first steps in Test Driven Development with Visual Studio. I have some questions regarding how to implement generic classes with VS 2010.
First, let's say I want to implement my own version of an ArrayList.
I start by creating the following test (I'm using in this case MSTest):
[TestMethod]
public void Add_10_Items_Remove_10_Items_Check_Size_Is_Zero() {
var myArrayList = new MyArrayList<int>();
for (int i = 0; i < 10; ++i) {
myArrayList.Add(i);
}
for (int i = 0; i < 10; ++i) {
myArrayList.RemoveAt(0); //should this mean RemoveAt(int) or RemoveAt(T)?
//VS doesn't know. Any work arounds?
}
int expected = 0;
int actual = myArrayList.Size;
Assert.AreEqual(expected, actual);
}
I'm using VS 2010 ability to hit
ctrl + .
and have it implement classes/methods on the go.
I have been getting some trouble when implementing generic classes. For example, when I define an .Add(10) method, VS doesn't know if I intend a generic method(as the class is generic) or an Add(int number) method. Is there any way to differentiate this?
The same can happen with return types. Let's assume I'm implementing a MyStack stack and I want to test if after I push and element and pop it, the stack is still empty. We all know pop should return something, but usually, the code of this test shouldn't care for it. Visual Studio would then think that pop is a void method, which in fact is not what one would want. How to deal with this? For each method, should I start by making tests that are "very specific" such as is obvious the method should return something so I don't get this kind of ambiguity? Even if not using the result, should I have something like int popValue = myStack.Pop() ?
How should I do tests to generic classes? Only test with one generic kind of type? I have been using ints, as they are easy to use, but should I also test with different kinds of objects? How do you usually approach this?
I see there is a popular tool called TestDriven for .NET. With VS 2010 release, is it still useful, or a lot of its features are now part of VS 2010, rendering it kinda useless?
Whenever I define a new property in my test code, and ask VS to generate that method stub for me, it generates both a getter and a setter. If I have something like int val = MyClass.MyProperty i'd like to to understand that (at least yet) I only want to define a getter.
Thanks
I see there is a popular tool called TestDriven for .NET. With VS 2010 release, is it still useful, or a lot of its features are now part of VS 2010, rendering it kinda useless?
It's still useful in case you use one of a number of different unit testing frameworks (nunit, mbunit, xunit, csunit, etc).
There are also other tools (like Visual Nunit) that provide visual studio integration for running unit tests.
To your code sample, why would you have a method RemoveAt(T obj)?
You can do RemoveAt(int index) and Remove(T obj) instead. Take a look at Microsoft's APIs (for example, for List<T>) that see how they set up the Remove methods for a generic collection.
And now for your points:
1: What would Add(int number) do? If I understand your intentions correctly, Add(10) can only be intepreted as "Add value 10 at the end of my collection". If you wanted to add a value at a particular index, you can (and probably should) name that method Insert: Insert(int index, T value).
2: sure, Visual Studio will interpret the method as void at first, but you can edit it to be something like
public class MyStack<T>
{
public T Pop()
{
}
}
The stubs built by pressing Ctrl+. are a convenience, but not gospel. You don't HAVE to always assign a return value to a variable. If you don't need it in a test, don't do it. If you want VS to pick up on a return type other than void, you can write a different unit test (e.g. that Pop() returns the last pushed value).
3: I'd test with the types that I see most frequently used in my code. If you're writing a public API, then test with as many types as possible. If you're using NUnit, look into using the [TestCase] attribute to help you avoid writing some duplicate code.
4: I still use TestDriven, but I haven't tried going without it, so I can't really make a useful comparison.
5: Just delete the setter if you don't need it. Some addon frameworks like ReSharper support more advanced code generation, including read-only properties.
I want to write a Visual Studio snippet which allows me to quickly create a class of the form:
public SomeClass
{
public SomeType SomeProperty { get; private set; }
public SomeClass(SomeType someProperty) { SomeProperty = someProperty; }
}
I want the parameter on the constructor to have the same name as the property, but lower-cased. I don't want to have to type the name twice. How do I do this?
I've already looked at the XML for snippets and I discovered that there are certain functions that can be used. For example, the built-in "switch" code snippet contains the following instruction:
<Function>GenerateSwitchCases($expression$)</Function>
According to this MSDN documentation page, there are three built-in functions that you can use in this <Function> tag. Unfortunately, neither of them does what I want (lower-case the first letter). Is it possible to define a function that I can then use in my snippet?
No this is not possible in Visual Studio today. The definition and execution of snippet functions is directly controlled by the C# language service. It is not currently an extensibility point. It is being considered for a future version of the product though.