How to decorate a part

How can I decorate an existing [Part] service? I just need this during SDK test executing.

Specifically, I want to decorate one method of the CSharpProjectFileLanguageService which has the [ProjectFileType(typeof(CSharpProjectFileType))] part attribute.

(I want to override GetPreprocessorDefines() to return dynamic conditional compilation symbols.)

Comment actions Permalink

You can't, really. You might be able to use IHideImplementation, but then you'd need to reimplement all of CSharpProjectFileLanguageService. Try this:

var configuration = project.ProjectProperties.TryGetConfiguration<ICSharpProjectConfiguration>(targetFrameworkId);
configuration.DefineConstants = "DEBUG;FOO;THING";

This will let you set the define constants that are then read by GetPreprocessorDefines.

Comment actions Permalink

Hi Matt,

Now I have another time the requirement to decorate a R# interface.

What will happen in the following scenario, if I use


R# extension A creates
MyComponentA: IReSharperComponent, I
R# extension B creates
MyComponentB: IReSharperComponent, I

Then one extension will also hide the other component, correct? Or would this even lead to a resolution error?

To solve this scenario in a clean way, it would be better to fully support decorating interfaces.

Comment actions Permalink

You'll get an exception. The component model isn't really designed to be THAT flexible. It will resolve a single interface to its most derived instance, so it allows extensions to override built in components, but it's not really intended for that use. It's there so that there can be a Visual Studio implementation of an interface that is used instead of a stand alone instance, when hosted in Visual Studio - it's an either/or mechanism, not a general purpose extension point. IHideImplementation is really only used for tests, so that components that (e.g.) talk to the internet to check for updates can be replaced so they work in CI.

Decorating interfaces sounds like an interesting idea, but it introduces other problems - how should they be ordered? Which decorator is called first? A better solution is to make the underlying component more extensible by default - take in a collection of components that can provide an implementation, look at the requirements to decide if that needs to be an ordered collection, allow all providers to handle the call, or just the first applicable, etc. The requirements for extensibility when dealing with an interface that expects a single implementation are usually bespoke, and better solved by changing the interface, rather than enabling a better kind of hack! That said, please file a request...

(I know this is a recap of a discussion we had on Skype, but I'd already typed it out, so I might as well post it! )


Please sign in to leave a comment.