Ok, so I've been learning c# and .net recently and one thing that seems to be missing from the c# documentation on http://msdn.microsoft.com/ that is present in the java documentation (e.g. ArrayList doc) is that a java class's documentation will say something like:
All Implemented Interfaces: Serializable, Cloneable, Iterable,
Collection, List, RandomAccess Direct Known Subclasses:
AttributeList, RoleList, RoleUnresolvedList
This allows me to find out which interfaces it implements and possibly discover interfaces I didn't know of yet. I can further click on an interface and get information on which classes implement it (in the standard classes anyway) and which interfaces extend it:
All Superinterfaces:
Iterable<E>
All Known Subinterfaces:
BeanContext, BeanContextServices, BlockingDeque<E>, BlockingQueue<E>, ...
All Known Implementing Classes:
AbstractCollection, AbstractList, AbstractQueue, AbstractSequentialList, ...
When using Microsoft's documentation I only get the base classes and possibly subclasses:
System.Object
System.MarshalByRefObject
System.IO.Stream
More...
"More..." being a link with a list of subclasses.
Is there a way in the documentation to find what interfaces a .Net class implements in a similar way that we can in the Java documentation?
Edit: I'm using Visual Studio Express and the publicly available documentation on MSDN so I suppose that the answer might be: yes you can, but you must pay up first for [full visual studio|MSDN subscription|...].
Documentation
Check out the Syntax section (e.g. for IObservableCollection(T)) in the documentation.
This gives the class declaration, including implemented interfaces
[SerializableAttribute]
public class ObservableCollection<T> : Collection<T>,
INotifyCollectionChanged, INotifyPropertyChanged
ILSpy
However, for classes for which documentation is not available, you can use a dissassembler such as ILSpy. Simply select a class, and it will show all base-types and derived types.
Object Browser
Finally, you can also use the Object Browser in Visual Studio (I'm not 100% sure it's in Express). View → Object Browser. This will show the base-types as you require.
In Visual Studio, place the caret on the thing you want to know about e.g. bool and press F12
It will show you the definition of the thing you pressed F12 on, so for bool:
namespace System
{
// Summary:
// Represents a Boolean value.
[Serializable]
[ComVisible(true)]
public struct Boolean : IComparable, IConvertible, IComparable<bool>, IEquatable<bool>
{
// Summary:
// Represents the Boolean value false as a string. This field is read-only.
public static readonly string FalseString;
...
Additionally you can open the Code Definition Window (View>Code Definition Window, Ctrl+W,D) which will show the above in a window - no button presses needed!
Resharper has a feature that allows that as well. If you press Ctrl+Shift+F1 then you can see a documentation about the class with full list of interfaces that it implements. You can decompile it using resharper to achieve the same result (though it's a little bit too much for what you need).
Resharper has Go to Base Symbols. you can use:
CTRL + U
Right click the class name > Navigate > Base Symbols
Resharper menu > Navigate > Base Symbols
This command allows you to navigate up the inheritance hierarchy to a
base type [including classes and interfaces] or method of the current symbol.
Here's a sample from a XAML.cs file
Related
I have the following class:
[ComVisible(true)]
[Guid("F8351C66-7F0E-4E38-AE64-9A262202E230")]
[ProgId("CarProject.CarFactory")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class CarFactory
{
public CarFactory()
{}
[DispId(0)]
public Car CreateCar(int tyres)
{
return new Car(tyres);
}
}
[ComVisible(true)]
[Guid("83f622b9-74f4-4700-9167-52c4ce9e79aa")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Car
{
[DispId(0)]
public int NumberOfTyres { get; private set; }
public Car(int tyres)
{
this.NumberOfTyres = tyres;
}
}
The Car object is created by a factory therefore the COM client uses only the _Car interface autogenerated. Note that there isn't a default constructor so the class cannot be instantiated through COM.
My question is: is the Guid attribute needed? I cannot find its value in the registry.
No, it is not needed since it will never be used. In fact, it is never needed and applying [Guid] is a pretty bad practice.
There are several other problems with this declaration style, discussing them all requires me to write a book and that is not very practical. It will be a lot easier for you to look at the decompiled type library so you can see what the client compiler sees. Use the Visual Studio Developer Command prompt, generates the type library if you don't have one yet with Tlbexp.exe. Run Oleview.exe, File > View Typelib and select the .tlb file. Highlighting the relevant details you now see:
importlib("mscorlib.tlb");
This is pretty awkward, the client programmer doesn't just have to add a reference to your type library but also the .NET type library for mscorlib.dll. Stored in the c:\windows\microsoft.net\framework\v4.0.30319 directory. Or v2.0.50727, the older version. Pretty unintuitive and does not often come to a good end. Note how you got in trouble with it in your previous question. Read on to find out why this happened.
[
odl,
uuid(BD7A2C0E-E561-3EBC-8BB7-1C72EE61D5B0),
hidden,
dual,
nonextensible,
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ClassLibrary171.Car")
]
interface _Car : IDispatch {
// etc..
}
This is the auto-generated "class interface", you already now about it. This is the one that the client compiler actually uses to make calls. Note the [uuid] attribute, same as the [Guid] attribute in C#. But it has a pretty random value. It was auto-generated, like the interface was. So using [Guid] in your declaration did not actually accomplish anything at all.
The [hidden] attribute as well as the leading underscore on the interface name tell an type browser tool (like Object Browser in VS) to hide the declaration. Made it important to use OleView to see the details. Otherwise a quirk that goes back to the kind of languages that don't have support for interfaces, old versions of Visual Basic (like VB6 and VBA) and scripting languages (like VBScript and JavaScript) being the primary examples. Such languages need to emulate them by making the interface look like a class, the only reason why you'd consider exposing the class at all.
[
uuid(83F622B9-74F4-4700-9167-52C4CE9E79AA),
version(1.0),
noncreatable,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ClassLibrary171.Car")
]
coclass Car {
[default] interface _Car;
interface _Object;
};
Note the [noncreatable] attribute. The type library exporter could see that client code can never create a Car instance since it has no default constructor. That in turn helps Regasm.exe figure out that registering the CLSID for Car is not necessary, that's why you could not find it back in the registry.
And note the _Object interface. Appeared because every .NET class derives from System.Object. And, likewise, the _Car interface also has the methods of Object (ToString, Equals, GetHashCode, GetType) since Car inherited them. This is how you ended up with the dependency on mscorlib.tlb. They might be useful to the client programmer, but that is not common and you generally certainly don't want to have to document them. The less you expose, the better.
Long story short, this happened because you used ClassInterfaceType.AutoDual. It is a convenience, but not a very good one and Microsoft strongly discourages it, recommending ClassInterfaceType.AutoDispatch instead. But that's only useful for scripting languages.
You avoid all this by declaring the ICar interface explicitly instead of letting the type library exporter generate it for you. It needs to be [ComVisible(true)] and the class needs to implement it. Now you can use ClassInterfaceType.None.
And now you can give the interface a [Guid]. But beware the bad practice this is, COM demands that interfaces are immutable. Once you exposed one in the wild, you can never change it again. Very important, COM has a nasty DLL Hell problem, caused by registration being machine-wide and you in general have no guarantee whatsoever that you can get the client programs recompiled. The crashes this can cause a very hard to diagnose. If you do have to change it then the interface needs a new [Guid] so both the old and the new interface can co-exist. Most trivially done by simply omitting the attribute entirely, the CLR already auto-generates it. Using [Guid] does allow creating interfaces that are binary compatible with an old interface declaration, but that's pretty hard to do correctly.
Say I have a class (shown as meta data) -- code lies in dll:
class Foo : IA, IB, IC, ID...
{
public void Bar(); // implementation
}
I would like to know where this Bar method was declared -- in IA, or IB, or... ... or it is fresh implementation -- without referring to any external sources like MSDN.
Can I do this in Visual Studio? If yes -- how?
If this was editable file (like my own code) this would be easy -- simply comment out for a while this method and see which interface becomes flagged.
If you are looking to get the source code of any .dll file you cannot do it with Visual Studio, But you can make use of decompiler tools like JustDecomplie , dotPeek etc
But even with these decompilers it is not guaranteed to get back the source code 100% accurately.
Remove the word public from the method and put, one at a time, IA. and all the other interfaces in front of the method name, then try to compile.
void IA.Bar() {
}
Note that more than one interface may have this method so you can try them all, or just paste in one copy of the method for each interface and see which ones work.
(This, by the way, is how you make different implementations for methods with the same name and signature from two different interfaces. I had to do this the other day with an indexer that one interface expected to be read-only and the other read/write. When the object is cast to one of the interfaces it uses the corresponding method.)
Alternately, ReSharper can do this for you. Simply hover over the method name with Resharper on.
If for example, I declare an interface class whose actual class type will only be determined on runtime, and by using VisualStudio when I right click the method call and click "Go To Implementation" I can find 3 implementations from classes that inherits the interface.
How can I, using Roslyn, get the method's implementation syntax nodes/symbols?
You're looking for SymbolFinder.FindImplementationsAsync.
Just look at the code that implements Go To Implementation. There's several public APIs on the SymbolFinder type that give you overrides/implementations/derived types, and each give you symbols back. Most of the code in the feature is just figuring out which is the right method to call, with some extra filtering that's specific for the feature. For example, if you have a derived type that's got an abstract member, the core functions will return that method, but it's not an implementation in a meaningful way for the sake of the feature.
In ReSharper, if I using the "Implement Interface" action on a class it creates a region named Implementation of IInterface. However, if I implement the interface manually then run a code cleanup, it wraps my interface members in a region named IInterface Members.
Why does it use two different naming conventions? If there a way to standardize this?
According to the R# docs for Reordering Type Members, the code clean up should reorder and wrap the implemented interface in a named region:
This XML code matches members that implement an interface, surrounds
them with regions and sorts by the name of the implemented interface.
The ${ImplementsInterface} variable contains the name of the interface
being implemented. If you do not want to insert regions around
interface implementations, remove the Group tag and ReSharper will
just sort members according to the name of the interface they are
implementing.
Check your settings and see if you may have overridden the default behavior. On the other hand, I have not personally testing the code clean up with the reordering and region wrapping, so this is somewhat of a best guess. But, hopefully it can point you in the right direction.
Edit
After reviewing the documentation in more detail and exploring all the editable templates with R#, I don't think there is a way to edit the text for the region's label.
I decompiled the JetBrains.ReSharper.Feature.Services.CSharp.dll and found what I believe to the be the source of the region's label:
Namespace: JetBrains.ReSharper.Feature.Services.CSharp.Generate
Class: CSharpGeneratorContext
Method: InsertWithRegions or CSharpGeneratorContext
Both methods have the string "Implementation of " + <some code> embedded in the dll, so it appears you will not be able to edit the default text.
I am using Microsoft REST Stark Kit Preview 2 to explore REST Collection WCF Service. Within the Service.svc.cs class, there are some classes and interfaces being used as base or component classes. For example:
public interface ICollectionService<TItem> where TItem : class
{
...
[WebHelp(Comment = "Returns the items in the collection in JSON format, along with URI links to each item.")]
[WebGet(UriTemplate = "?format=json", ResponseFormat = WebMessageFormat.Json)]
ItemInfoList<TItem> GetItemsInJoson();
...
}
[CollectionDataContract(Name = "ItemInfoList", Namespace = "")]
public class ItemInfoList<TItem> : List<ItemInfo<TItem>> where TItem : class
...
where ICollectionServices and ItemInfoList are all in Microsoft.ServiceModel.Web.dll in the Preview 2. I would change those item's attributes such as WebHelp's Comment and CollectionDataContract's Name so that I could customize help message and templates for xml node names. The Preview 2's change with embedding those interfaces and classes in its dll makes it difficult to do any customization.
So my question is that if there is any way to change a class or interface's attributes or overwrite their existing attributes so that I don't need to get the source codes to make changes?
No, you can't.
What you might be able to do is inherit from the classes. If the attributes in question are not inheritable, you can add your own to your subclasses to override them.
I checked the CollectionDataContractAttribute, and it, at least, is not inheritable. That means if you create a subclass, you can apply a different CollectionDataContract attribute to that subclass.
[CollectionDataContract(Name = "MyItemInfoList", Namespace = "MyNamespace")]
public class MyItemInfoList<TItem> : ItemInfoList<TItem> where TItem : class
However, with members, this approach will only work if they are virtual, so you can override them.
Attributes are burnt in at compile time, and cannot for reflection be set at runtime. There are a few things you can do in "ComponentModel", but they wouldn't apply here. The only other common case here is for "i18n", where an attribute might be designed to pick up different values at runtime (from resx etc, based on a key rather than the description being set in the code) - and again, this doesn't apply in this case.
So, no.
In terms of REST Start kit Preview 2's customization issue, it look like the customization was disabled when the template basic classes are moved to its core dll. According to WCF REST Start kit forum at ASP.NET, the customization features will be back in the next release (soon).