Open StephenMLucas opened 2 years ago
Note that although it's not the root cause this feature would also provide a mitigation for issues like https://github.com/microsoft/CsWinRT/issues/1073 where a problematic dependency is not actually required.
YES! I definetly agree this is option is a must have.
Thanks @StephenMLucas for this feedback. If I am understanding your proposal, are you saying we should expand our current CsWinRTExcludes mechanism to exclude methods / members of included types which references types that are excluded? So for instance, if a type has 5 methods and one of those methods had a reference to a type that was in the CsWinRTExcludes, then the type would be projected with just 4 methods rather than 5.
This does make me wonder whether we should expand the CsWinRTIncludes / CsWinRTExcludes mechanism to support operating on methods and not just namespaces and types. Something we will need to think about and consider, but I do see how it can be helpful with embedded support.
Hi @manodasanW - yes that's correct.
I agree that extending the includes mechanism down to method level granularity would also have the same functional outcome. From a workflow perspective I think on balance it's usually going to be more convenient to think at the type level and then exclude problematic referenced types rather than choosing the individual methods to include or exclude. But they are certainly complementary approaches and if one is significantly easier to implement then having either would help with these scenarios.
Here's my scenario: I want to use the BluetoothLEAdvertisementWatcher
, but before you know it, you're spending forever trying to figure out which namespaces you need to include to generate valid code that'll compile, and your list of APIs getting included just grows and grows and grows.
What I'd like to do is just specify the class Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher
and all the required types to generate this will be included - nothing less, nothing more. The code generator today generates invalid non-compiling code because it doesn't walk the dependency graph and figure out what is actually needed.
So perhaps we could just specific not the class, but the members we intend to use, and only their dependencies would be included.
I ended up giving up and just using reflection to the APIs I need instead of using this generator :-(
Like @dotMorten I also fail on Bluetooth CsWinRTIncludes
. In my case, I discover a Bluetooth LE device by a known service id, wirte/read from a characteristics. No fanciness here. To only other type outside of the Bluetooth namespace I need is Windows.Storage.Streams.DataReader
.
Honestly, the only reason I access WinRT APIs are for device access. And I think most of these namespaces are cluttered with references to other namespaces for edge cases. I think the embedded concept is doomed until this is not resolved.
I am down to the following (without even knowing whether it will work in the end) ...
<PropertyGroup>
<TargetFrameworks>net8.0-windows</TargetFrameworks>
<CsWinRTEmbedded>true</CsWinRTEmbedded>
<CsWinRTWindowsMetadata>10.0.19041.0</CsWinRTWindowsMetadata>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.4" />
</ItemGroup>
<PropertyGroup>
<CsWinRTIncludes>
Windows.Foundation;
Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisement
Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher;
Windows.Devices.Bluetooth.Advertisement.BluetoothLEScanningMode;
Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementReceivedEventArgs;
Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisement
Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementBytePattern;
Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementReceivedEventArgs;
Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementPublisher;
Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcher;
Windows.Devices.Bluetooth.Advertisement.BluetoothLEManufacturerData;
Windows.Devices.Bluetooth.Advertisement.IBluetoothLEManufacturerData;
Windows.Devices.Bluetooth.BluetoothLEAppearance;
Windows.Devices.Bluetooth.BluetoothSignalStrengthFilter;
Windows.Devices.Bluetooth.BluetoothDeviceId;
Windows.Devices.Bluetooth.BluetoothLEDevice;
Windows.Devices.Bluetooth.GenericAttributeProfile;
Windows.Devices.Bluetooth.BluetoothAddressType;
Windows.Devices.Bluetooth.BluetoothCacheMode;
Windows.Devices.Bluetooth.BluetoothConnectionStatus;
Windows.Devices.Bluetooth.BluetoothError;
Windows.Devices.Bluetooth.IBluetoothDeviceId;
Windows.Devices.Bluetooth.IBluetoothLEAppearance;
Windows.Devices.Bluetooth.IBluetoothSignalStrengthFilter;
Windows.Devices.Bluetooth.IBluetoothLEDevice;
Windows.Storage.Streams.IBuffer;
Windows.Storage.Streams.Buffer;
Windows.Storage.Streams.IInputStream;
Windows.Storage.Streams.IOutputStream;
Windows.Storage.Streams.InputStreamOptions;
Windows.Storage.Streams.IRandomAccessStream;
Windows.Storage.Streams.IContentTypeProvider;
Windows.Devices.Enumeration.IDeviceAccessInformation;
Windows.Devices.Enumeration.DeviceAccessChangedEventArgs;
Windows.Devices.Enumeration.IDeviceAccessChangedEventArgs;
Windows.Devices.Enumeration.DeviceAccessStatus;
Windows.Devices.Enumeration.DeviceAccessInformation;
Windows.Devices.Enumeration.DeviceClass;
</CsWinRTIncludes>
<CsWinRTExcludes>
Windows.Foundation.Diagnostic;
Windows.Devices.Bluetooth.IBluetoothLEDevice2;
Windows.Devices.Bluetooth.IBluetoothLEDevice3;
Windows.Devices.Bluetooth.IBluetoothLEDevice4;
Windows.Storage.Streams.IRandomAccessStreamReferenceStatics;
Windows.Storage.Streams.RandomAccessStreamReference;
Windows.Foundation.PropertyType;
</CsWinRTExcludes>
</PropertyGroup>
with the following remaining errors (on the core BluetoothLEDevice
type)
CsWinRT\Windows.Devices.Bluetooth.cs(593,52): error CS0234: [..] "DeviceInformation" [..] "Windows.Devices.Enumeration" [..]
As soon as I add Windows.Devices.Enumeration.DeviceInformation
hell breaks loose and I am up to 39 errors and with the next DeviceWatcher
I am up to over 100 errors.
I will be happy with any way of breaking this dependency graph issue: Auto-analyzing the used WinRT objects, enumerating namespaces with automatic trimming, manual enumeration of excluded members.
@manodasanW any updates here?
I would like to given example of why this issue is important to me.
In my app I'm using only this line of WinRT related code. The app runs in an MSIX package and this just gets the version number of the package:
var version = Windows.ApplicationModel.Package.Current.Id.Version;
An extremly limited use of WinRT like this, should be a great use case for the embedded support in CsWinRT (at least that's what I thought).
It seems to be working nicely, however the way to get there is pretty painful (all artisanally handcrafted):
Proposal: Allow embedded projects to suppress generating members that reference types from specified namespaces
Summary
The current
<CsWinRTIncludes>
section allows namespaces to be included in the code generation, a second<CSWinRTExcludes>
section could be used to list namespaces and types that are explicitly not wanted for the embedded projection. Any members that would produce a reference to an excluded type or namespace would be omitted from the projection.Rationale
Important Notes
Open Questions