如何将 "IStorageItem" 的实现传递给 DataPackage.SetStorageItems(items) 并且不在 UWP 上引发 InvalidCastException?

How can I pass an implementation of "IStorageItem" to DataPackage.SetStorageItems(items) and don't get an InvalidCastException raised on UWP?

我正在开发一个能够共享其文件的 UWP 应用程序。我遵循 the documentation from Microsoft 并且解决方案非常有效。

这是我的实现:

public void ShareLocalFile(LocalFileToShare file)
{
    DataTransferManager.GetForCurrentView().DataRequested += async (sender, args) =>
    {
        var deferral = args.Request.GetDeferral();

        try
        {
            var storageFile = await StorageFile.GetFileFromPathAsync(file.FilePath).AsTask();

            args.Request.Data.SetStorageItems(new[] { storageFile });
        }
        finally
        {
            deferral.Complete();
        }
    };

    DataTransferManager.ShowShareUI();
}

但是,该应用程序存储的所有文件都没有人类可读的名称,这让用户对共享感到不安。 因此,我想共享一个具有替代名称的文件,而不实际在文件系统上重命名它,因为文件是在第三方 reader 中打开的。另外,文件比较大,用新的名字复制也不是一个好的选择。

首先我想我可以做一个符号 link 但是 it's only possible with Administrator rights

然后我看看the signature of "void DataPackage.SetStorageItems(IEnumerable value)" method and guessed that it's probably possible to pass there my own implementation of IStorageItem我做了什么:

public class StorageItemWithAlternativeName : IStorageItem
{
    private readonly IStorageItem storageItem;

    public StorageItemWithAlternativeName(IStorageItem storageItem, string alternativeItemName)
    {
        this.storageItem = storageItem;
        Name = alternativeItemName;
    }

    public string Name { get; }

    // the interface implementation omitted for briefness but it simply delegates all actions to the decorated storageItem
}

public static class LocalFileToShareExtensions
{
    public static async Task<IStorageItem> GetStorageItem(this LocalFileToShare file)
    {
        var storageFile = await StorageFile.GetFileFromPathAsync(file.FilePath).AsTask();

        if (!string.IsNullOrWhiteSpace(file.AlternativeFileName))
        {
            storageFile = new StorageItemWithAlternativeName(storageFile, file.AlternativeFileName);
        }

        return storageFile;
    }
}

我在这里失败了。该错误非常愚蠢 - SetStorageItems 方法抛出 InvalidCastException: “不支持这样的界面。 该集合包含无法转换为只读形式的项目。"

我调查了 windows 事件日志并找到了以下条目:

Faulting application name: [MyApp].Windows.exe, version: 7.0.0.0, time stamp:    0x5bb69bfe
Faulting module name: combase.dll, version: 10.0.17763.253, time stamp: 0xa3f81b2d
Exception code: 0xc000027b
Fault offset: 0x00209931
Faulting process id: 0x4ee4
Faulting application start time: 0x01d4be3ccca1f00f
Faulting application path: [PathToMyApp].Windows.exe
Faulting module path: C:\WINDOWS\System32\combase.dll
Report Id: 35999df1-6b4f-4675-a821-a84e6ea0cfb4
Faulting package full name: [MyAppPackageName]
Faulting package-relative application ID: App

似乎 DataPackage 对象与 COM 通信,所以我也尝试了我的程序集的 [assembly: [ComVisible(true)] 属性,但我没有成功。

问题是我怎样才能使系统变笨并共享一个不同名称的文件?是否可以将我自己的实现传递给 UWP SDK 方法?因为现在它违反了the Liskov substitution principle.

我将不胜感激!

请尝试使用带参数 readOnly:false 的重载方法 SetStorageItems,如下所示:

args.Request.Data.SetStorageItems(new[] { storageFile }, false);