Replies: 14 comments 24 replies
-
That was changed over two years ago in preparation for v11. The API still public, so there's no appetite to make breaking changes to it outside of new major versions. Implementations are intended for platform implementers, not applications. If you are implementing a platform, then the suggested approach is to put If you're writing an application and there's missing clipboard functionality, then the best approach is create a new issue with the scope of work, implement it yourself, and upstream it into Avalonia. If the missing clipboard functionality isn't appropriate for Avalonia, then stick it into a separate class library with |
Beta Was this translation helpful? Give feedback.
-
Yes, but was was only merged very recently for version 11.1.4, so it's a breaking change that just surfaced.
Decorators are a well-known and very useful pattern, which are now made impossible because of this attribute.
Not necessarily missing, but I might have a need to customize and specialize behavior.
That is of course nice, when realistic. But it's often hard to handle a delay for a year or two before the feature is merged into a public release, and depending on the application, the requirements for a specific app may be much less demanding than for a general purpose feature into the platform. It's also non-trivial to set up a development environment for Avalonia UI to do just a small feature add unfortunately, so it's a little hard to motivate the effort at times as much as I would like. I have contributed previously to other large project.
That's a global flag, and thus a little like swatting a fly with a sledgehammer. There's likely to be unwanted side effects. Creating a separate library just for one little decorator seems a little too much. I realize I probably can't fight city hall on this one, but I honestly don't see the benefit of this attribute on this type of API. It's not an unstable private API. If it's really seen as an unstable private API, then perhaps it should be made Anyway, thanks for the response, and for Avalonia UI! |
Beta Was this translation helpful? Give feedback.
-
Ah, I see. This is due to #16626 where being able to build without opting in was mistakenly possible.
How are you decorating when the platform-specific implementations are not publicly accessible nor can you replace their use within Avalonia without opting in, AFAIK? Why should run-of-the-mill apps be able to tweak native platform implementations by default?
I'm just one community contributor trying to give you the rationale, not a core maintainer. Avalonia is created across multiple packages instead of a monolith. Avalonia reserves space for itself (and its packages), enough space for third-party platform implementers, and less space to application developers. |
Beta Was this translation helpful? Give feedback.
-
As @stevemonaco said, it would be great to understand the real usecase. If it's a bug, it needs a fix. If it's a missing feature, it needs to be added at some point in time. So please take your time to carefully explain what's your reason for need to implement this interface. Best with some sample code. Then we can discuss whatever way to go. Tip If you need priority on a certain feature or fix, you can request it in case you have a support agreement. |
Beta Was this translation helpful? Give feedback.
-
Hi! As mentioned, the reason is to decorate the platform implementation of a public interface. There are numerous reasons why this might be useful and legitimate, from adding missing functionality, to work around bugs, to facilitate debugging, adding logging, unit testing and many other reasons. A decorator is a very powerful design pattern, but now made impossible by the marking of a public interface such as It's not about implementing something the platform implements, but even so, I don't see why there's a need to forbid it. A warning, that is possible to disable, maybe... but this causes a compilation error. In fact, I could argue that it kind of destroys most of the benefits of having an interface at all! One of the absolute core benefits of interfaces is the ability to provide alternate implementations, now this possibility is removed for all but the platform developers. I can't even inject a unit test fake or mock with this restriction in place! To demonstrate, I've put together a self-contained sample app here: https://github.com/xecrets/clipboard-decorator . It's both somewhat elaborate, but also a bare-bones sample thus not demonstrating best practices for production code in some ways. It compiles and works on Windows and Linux Ubuntu 22.04 - I've not tested it elsewhere. What this sample does is provide simple support for accepting files on the clipboard on Linux, which is not supported otherwise. But, as mentioned, even if if this is or will be supported in the future, there are still numerous reasons why you might want to decorate the platform implementation. It's now using Avalonia UI 11.1.3 and compiles and works fine. If upgraded to 11.1.4, it no longer compiles because of the added I do not agree that an acceptable solution is to add IMHO it's a bug. The attribute should never have been added. It's also a breaking change, and should be marked and documented as such if the maintainers insist on it. |
Beta Was this translation helpful? Give feedback.
-
Same problem here with the |
Beta Was this translation helpful? Give feedback.
-
The approach in your example is problematic: IClipboard clipboard = mainWindow.Clipboard ?? throw new InvalidOperationException("No clipboard!");
IStorageProvider storageProvider = mainWindow.StorageProvider ?? throw new InvalidOperationException("No storage provider!");
IClipboard myClipboad = OperatingSystem.IsLinux() ?
new MyLinuxClipboard(clipboard, storageProvider) :
new MyDefaultClipboard(clipboard);
mainWindow.DataContext = new MainWindowViewModel(myClipboad); You're consuming Avalonia types directly in the ViewModel. Ideally, the ViewModel should not know Avalonia exists. Instead, you should create your own interface or service class with a public API that matches your app's requirements (not simply a 1:1 There's no point in implementing I don't see any problem with requiring an opt-in for such advanced functionality to keep a happy path for the bulk of the user base, but the team decides that. |
Beta Was this translation helpful? Give feedback.
-
Made this a discussion for now as we need to discuss the API here. |
Beta Was this translation helpful? Give feedback.
-
Right. As I said it's a "sample thus not demonstrating best practices for production code". But somewhere I would like to consume
Of course I can do that when I have control over all of the code, which is essentially what I did to work around the current situation and get on with my app. However, that is only possible when I have full control over all consumers if the clipboard. If I am using a third party component, or even framework library code that expects a
As mentioned, there are many scenarios when there's a good reason to implement for example This is not the only affected interface either, The interface API in question is a stable, public, API. It's not an internal, or private, or unstable API. What could break by allowing an app developer to 'implement' it, for whatever reason? |
Beta Was this translation helpful? Give feedback.
-
The problem is that even adding a member to an interface is considered a breaking change, so allowing clients to implement e.g. |
Beta Was this translation helpful? Give feedback.
-
There are dozens of types with
These are clearly not intended to be stable, public interfaces in the same way that an API like
As project property? Can't. |
Beta Was this translation helpful? Give feedback.
-
Please understand that pre-11.0 Avalonia didn't really have a stable public API and we were following "make everything extendable in case we need to extend it later" rule. When stable ABI got introduced with 11.0, we've had a choice of either spending extra months of work on redesigning all APIs (e. g. IClipboard would have become In retrospect, it following "make everything extendable" was a huge mistake and we should have made everything internal in the first place (I now have a strong belief that not having automatic This decision will not get revisited now since we don't want to break most common usage scenarios that are not trying to implement private APIs in favor of some extra extensibility that can be achieved on app level by introducing an extra level of abstraction. As of the "shipping an analyzer" idea, I'd like to remind that .NET is not C#, is not owned by C# devs and has other languages compiled without Roslyn. The reference assembly way of restricting access to APIs works for other languages too. |
Beta Was this translation helpful? Give feedback.
-
I'm closing this discussion since we won't be changing the way NonClientImplementable works |
Beta Was this translation helpful? Give feedback.
-
This also breaks Fabulous.Avalonia mobile support fabulous-dev/Fabulous.Avalonia#261. We relied on So this is essentially game over for F# Fabulous Avalonia mobile support. Would you consider removing |
Beta Was this translation helpful? Give feedback.
-
Describe the bug
In commit d757326 recently merged and now part of 11.1.4, the
[NotClientImplementable]
attribute was added to theIClipboard
interface (and a lot of other interfaces).Considering the fact that the Avalonia implementations of IClipboard are still incomplete and not fully equivalent between the platforms, for example Linux does not present the default data formats, this is very unfortunate.
The addition of this attribute prevents an implementer to add their own decorated implementations to work around the issues present in the Avalonia implementation.
This is not an internal API that is normally unused by implementers, it's a public API accessible as
TopLevel.Clipboard
. If Avalonia in the future breaks this API in a way that would break a decorating implementation, it'll typically break any normal use of it as well. In this case I do not see any benefit at all in forbidding client implementations (decorators to work around Avalonia limitations typically).To Reproduce
Have code that implements
IClipboard
and upgrade to 11.1.4 . Compilation breaks with a messageThis interface or abstract class is -not- implementable by user code !
.Expected behavior
I would expect a client implementation of IClipboard to be possible just as it was before 11.1.4 .
Avalonia version
11.1.4
OS
Windows, macOS, Linux
Additional context
No response
Beta Was this translation helpful? Give feedback.
All reactions