When writing an VSIX and you want to access information about the given solution you can simply do DTE2.Solution which will return Solution, so far so good. When looking at the MSDN I can see that there exist multiple solution interfaces: Solution, Solution2, Solution3 and Solution4.
I noticed that the VSIX SDK rather often does this, for whatever reason, in order to offer different functionality. In this case I can't really spot any big difference and I am not really sure when I should use which. Should you always go for Solution4 since it implements all the predecessors?
... for whatever reason, in order to offer different functionality
These are COM interfaces so they're subject to COM rules. Once an interface is published, it is immutable, so adding functionality is done by defining a new interface that inherits from the old.
Numeric suffixes were the convention Microsoft used for versioning COM interfaces. .NET guidelines for interfaces advise against this but, for consistency, the pattern continues in Visual Studio.
Querying a COM interface involves reference counting. That means a call to QueryInterface to get a pointer to the desired interface, and ultimately a call to Release to tell the object you no longer need the reference. The object itself is responsible for its lifetime. The constructor (called by the object's class factory) starts its reference count at 1, and Release deallocates the memory (deletes itself) when the reference count hits 0.
Note that "reference" in this context is not the same as a .NET reference. It's a counted copy of a pointer to one of the object's interfaces.
In the early days, it took a bit of work to make sure you handled the reference correctly. If you can query a newer interface with the combined functionality, that was less work than querying both interfaces separately and ensuring that both were released properly. Inheriting an interface made things easier by reducing reference management.
Now, we have smart pointers, like CComPtr/_com_ptr_t, that can handle those details for you. In the managed world, Runtime-Callable Wrappers (RCW) count that among their responsibilities.
In .NET, it's just as easy to create a new interface as it is to inherit an existing one, and just as easy to use the interface in either case. It's just a matter of a reference cast and sometimes that happens implicitly.
C# 8 adds default implementations but that's a .NET-specific feature. Remember, Visual Studio is still using COM interfaces at its core. Default implementations violate the COM rules.
Should you always go for Solution4 since it implements all the predecessors?
That depends on what you're targeting. As a general rule, use the minimal interface version that has the members you need. If you need members from Solution and Solution3, use Solution3, but not Solution4.
On the other hand, if you know you're targeting at least a version of Visual Studio that implements Solution4, there's no reason you couldn't use Solution4. Once you're certain that you're not accidentally preventing your extension from running in the Visual Studio versions you want to target, it falls to your preference.
Related
I have a product that I need to add dynamic versioning to our core level components, so that the main application can check for version inconsistencies before allowing certain things to execute. Some background:
All components implement an interface that I have defined
There is no base class that the components derive from, they all implement the root interface directly
I can add a new int Version property and/or methods to the interface
I need to maintain backwards compatibility with DLLs that already "in the wild" and deployed. If a DLL doesn't implement the version checking APIs (because its old), assume it will work properly
So I was thinking of adding a bool CheckVersion() method to the interface, and then checking if that method exists before invoking it. If the method doesn't exist, then just don't invoke it.
I don't like the idea of checking if the method exists because it is expensive and clutters up the code (e.g., "Why is this weird invocation check necessary?")
Anyone have any better ideas?
I have a C# interface, IFoo, which can be implemented by multiple parties in multiple projects. What I want to do is version the interface so that I can identify which version of the interface an implementation was developed against.
Is there a preferred/conventional way of doing this? I thought about putting a read-only InterfaceVersion property into the interface spec, but that can be defined by the implementer, not by me as the designer of the interface, and so isn't what I want.
This is a very complicated topic when you consider the full impact of various decisions. I have started the process of documenting this in the following topic:
Assembly Versioning in Extensible Applications
This document focuses on Visual Studio 2010 and newer, which is itself an extensible application with multiple versions released to date. The extension mechanism in place is MEF, but the rules and restrictions it imposes still apply to other extension mechanisms.
This document is a work-in-progress. Suggestions and/or problems can be reported on the issue tracker.
Typically one doesn't version an interface because it is considered a contract (and contracts should be enforced not broken). Typically a new interface is created with the new functionality (IFoo2 perhaps) and classes that need to participate in the new contract will then implement that.
public class Foo : IFoo, IFoo2
{
// Implementation goes here
}
but that can be defined by the implementer, not by me as the designer
of the interface, and so isn't what I want
This passage contains the answer to your own question. What you want is something that can only be defined by you (the designer), so it has to be something 100% contained in the assemblies you provide. Assemblies contain types, therefore this something must be a type.
Obviously you cannot change any interface after you have shipped it (that would break the code all your clients), so the only option remaining is to define a new interface. Implementers can then opt-in to the new version by choosing to implement it.
Some time I ago I was working on a major refactoring of an old Win32 program implemented with COM, and there were various parts that were implemented with C# (.NET). During my work on this project, I ran across a Microsoft page on COM programming in C# that recommended C# classes explicitly implement COM interfaces, rather than implicity. I recently tried to remember why, and I couldn't. I also couldn't find the page on the MSDN site again. Can anybody please tell me why Microsoft might recommend this ?
Hmm, that makes a wee bit of sense, COM is pure interface-based programming and the actual implementation of the interfaces should be hidden. Implementing interface methods explicitly gets you that automatically because they cannot be public.
Actually doing this is quite pointless, you could (and should) simply apply the [ClassInterface(ClassInterfaceType.None)] attribute to the class. That by itself ensures that the implementation isn't exposed, only the interfaces implemented by the class are visible. Implementing the interface methods explicitly isn't actually good enough. Because you cannot hide the fact that your class inherits System.Object. Which exposes the four public methods of Object and puts a reference to mscorlib.tlb in your type library, a reference that a real COM client will never use. It will almost always work because the odds that the compiler that uses your class runs on a machine that doesn't have .NET installed are pretty small. But very yucky nonetheless, it isn't actually required. Only the machine that uses the class needs it installed.
Just don't do this. Declare the interfaces you implement, give them the [InterfaceType(ComInterfaceType.InterfaceIsDual)] attribute to allow them to be used both early and late bound. And hide the actual implementation of them with [ClassInterface(ClassInterfaceType.None)]. Only sensible way.
It's old, but from here: http://msdn.microsoft.com/en-us/library/aa288461%28v=VS.71%29.aspx they mention implementing an interface explicitly so you can implement multiple interfaces that have the same member names.
This also requires that the user of your class cast an instance of your class to the appropriate interface.
As for why this is especially important for COM: my first guess is so that COM can call one set of methods while managed code may call another. However, I'm guessing here.
Greetings all,
I’m working on a C# program that requires being able to get the index of the hot item in Windows 7 Explorer’s new ItemsView control. Fortunately, Microsoft has provided a way to do this through UI Automation, by querying custom properties of the control.
Unfortunately, the System.Windows.Automation namespace inexplicably does not seem to provide a way to query custom properties! This leaves me with the undesirable position of having to completely ditch the C# Automation namespace and use only the unmanaged COM version. One way to do it would be to put all the Automation code in a separate C++/CLI module and call it from my C# application. However, I would like to avoid this option if possible, as it adds more files to my project, and I’d have to worry about 32/64-bit problems and such.
The other option is to make use of the ComImport attribute to declare the relevant interfaces and do everything through COM-interop. This is what I would like to do. However, the relevant interfaces, such as IUIAutomation and IUIAutomationElement, are FREAKING HUGE. They have hundreds of methods in total, and reference tons and tons of interfaces (which I assume I would have to also declare), almost all of which I will never ever use. I don’t think the UI Automation interfaces are declared in any Type Library either, so I can’t use TLBIMP.
Is there any way I can avoid having to manually translate a bajillion method signatures into C# and instead only declare the ten or so methods I actually need? I see that C# 4.0 added a new “dynamic” type that is supposed to ease COM interop; is that at all relevant to my problem?
Thanks
The most important thing (from the perspective of calling a COM method from C#) is that the methods appear in the interface in the right order. If you're not using a method, you can just declare it as void and nothing bad will happen (unless you actually call it!). This saves you from having to work out the correct signatures and define all the other types, etc. For example,
[ComImport, Guid("30cbe57d-d9d0-452a-ab13-7ac5ac4825ee"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IUIAutomation
{
void CompareElements();
void CompareRuntimeIds();
void GetRootElement();
// 50 or so other methods...
// ... define only the signatures for the ones you actually need
}
The methods should be defined in exactly the same order they appear in UIAutomationClient.h (in the Windows SDK).
What is the best approach for defining Interfaces in either C# or Java? Do we need to make generic or add the methods as and when the real need arises?
Regards,
Srinivas
Once an interface is defined, it is intended to not be changed.
You have to be thoughtful about the purpose of the interface and be as complete as possible.
If you find the need, later, to add a method, really you should define a new interface, possibly a _V2 interface, with the additional method.
Addendum: Here you will find some good guidelines on interface design in C#, as part of a larger, valuable work on C# design in general. It generally applies to Java as well.
Excerpts:
Although most APIs are best modeled using classes and structs, there are cases in which interfaces are more appropriate or are the only option.
DO provide at least one type that is
an implementation of an interface.
This helps to validate the design of
the interface. For example,
System.Collections.ArrayList is an
implementation of the
System.Collections.IList interface.
DO provide at least one API consuming
each interface you define (a method
taking the interface as a parameter or
a property typed as the interface).
This helps to validate the interface
design. For example, List.Sort
consumes IComparer interface.
DO NOT add members to an interface that
has previously shipped. Doing so
would break implementations of the
interface. You should create a new
interface to avoid versioning
problems.
I recommend relying on the broad type design guidelines.
To quote Joshua Bloch:
When in doubt, leave it out.
You can always add to an interface later. Once a member is a part of your interface it is very difficult to change or remove it. Be very conservative in your creation of you interfaces as they are binding contracts.
As a side note here is an excellent interview with Vance Morrison (of the Microsoft CLR team) in which he mentions the possibility of a future version of the CLR allowing "mixins" or interfaces with default implementations for their members.
If your interface is part of code that is shared with other projects and teams, listen to Cheeso. But if your interface is part of a private project and you have access to all the change points then you probably didn't need interfaces to begin with but go ahead and change them.
If the interface is going to be public, I feel that a good deal of care needs to be put into the design because changes to the interface is going to be difficult if a lot of code is going to suddenly break in the next iteration.
Changes to the interface needs to be taken with care, therefore, it would be ideal if changes wouldn't have to be made after the initial release. This means, that the first iteration will be very important in terms of the design.
However, if changes are required, one way to implement the changes to the interface would be deprecate the old methods, and provide a transition path for old code to use the newly-designed features. This does mean that the deprecated methods will still stick around to prevent the code using the old methods from breaking -- this is not ideal, so it is a "price to pay" for not getting it right the first time around.
On a related matter, yesterday, I stumbled upon the Google Tech Talk: How to Design a Good API and Why It Matters by Joshua Bloch. He was behind the design and implementation of the Java Collection libraries and such, and is the author of Effective Java.
The video is about an hour long where he goes into details and examples about what makes a good API, why we should be making well-designed APIs, and more. It's a good video to watch to get some ideas and inspiration for certain things to look out for when thinking about designing APIs.
Adding methods later to an interface immediately breaks all implementations of the interface that didn't accidentaly implement those methods. For that reason, make sure your interface specification is complete. I'd propose you start with a (sample) client of the interface, the part that actually uses instances of classes implementing said interface. Whatever the client needs must be part of the interface (obviously). Then make a (sample) implementation of the interface and look what additional methods are both generally usefull and available (in possible other implementations) so they should also be part of the interface. Check for symetry completeness (e.g. if there is an "openXYZ", there should also be a "closeXYZ". if there is an "addFooBar", there should be a "removeFooBar". etc.)
If possible, let a coworker check your specification.
And: Be sure you really want an interface. Maybe an abstract base class is a better fit for your needs.
Well, it really depends on your particular situation. If your team is the sole user/maintainer of that interface, then by all means, modify it as you see fit and forget all about that "best practice blabla" kind of stuff. It is YOUR code after all... Never blindly follow best pracice stuff without understanding its rationale.
Now, if you're making a public API that other team or customer, will work with (think plugins, extension points or things like that) then you have to be conservative with what you put in the interface. As other mentionned, you may have to add _V2 kind of interface int these cases. Microsoft did with several web browser COM interfaces.
The guidelines Microsoft publishes in Framework Design Guidelines are just that: guideline for PUBLIC interface. Not for private internal stuff; tough many of them still apply. Know what applies or not to your situation.
No rule will make up for lack of common sense.