打包 uri 验证

发布于 2024-09-05 00:20:08 字数 197 浏览 5 评论 0原文

验证是否可以找到包 uri 的最简单方法是什么?

例如,

pack://application:,,,Rhino.Mocks;3.5.0.1337;0b3305902db7183f;component/SomeImage.png

如何检查图像是否确实存在?

干杯,
贝里尔

What is the simplest way to verify that a pack uri can be found?

For example, given

pack://application:,,,Rhino.Mocks;3.5.0.1337;0b3305902db7183f;component/SomeImage.png

how would I check whether the image actually exists?

Cheers,
Berryl

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鱼忆七猫命九 2024-09-12 00:20:08

我找不到这个问题的简单答案,因此我最终编写了自己的代码来完成与图像资源相关的三件事:
(1) 具有包 uri 的字符串表示形式(数据绑定)
(2)验证图像是否位于我认为它所在的位置(单元测试)
(3) 验证 pack uri 是否可用于设置图像(单元测试)

这并不简单,部分原因是因为 pack uri 一开始有点令人困惑,并且有多种风格。此代码适用于表示 VS 程序集中包含的图像的包 uri(本地程序集或具有“资源”构建操作的引用程序集)。此 msdn 文章 阐明了这在上下文中的含义。您还需要了解更多有关程序集和构建的信息,这可能比最初看起来更好希望

这对其他人来说更容易,
贝里尔

    /// <summary> (1) Creates a 'Resource' pack URI .</summary>
    public static Uri CreatePackUri(Assembly assembly, string path, PackType packType)
    {
        Check.RequireNotNull(assembly);
        Check.RequireStringValue(path, "path");

        const string startString = "pack://application:,,,/{0};component/{1}";
        string packString;
        switch (packType)
        {
            case PackType.ReferencedAssemblySimpleName:
                packString = string.Format(startString, assembly.GetName().Name, path);
                break;
            case PackType.ReferencedAssemblyAllAvailableParts:
                // exercise for the reader
                break;
            default:
                throw new ArgumentOutOfRangeException("packType");
        }
        return new Uri(packString);
    }

    /// <summary>(2) Verify the resource is located where I think it is.</summary>
    public static bool ResourceExists(Assembly assembly, string resourcePath)
    {
        return GetResourcePaths(assembly).Contains(resourcePath.ToLowerInvariant());
    }

    public static IEnumerable<object> GetResourcePaths(Assembly assembly, CultureInfo culture)
    {
        var resourceName = assembly.GetName().Name + ".g";
        var resourceManager = new ResourceManager(resourceName, assembly);

        try
        {
            var resourceSet = resourceManager.GetResourceSet(culture, true, true);

            foreach (DictionaryEntry resource in resourceSet)
            {
                yield return resource.Key;
            }
        }
        finally
        {
            resourceManager.ReleaseAllResources();
        }
    }

    /// <summary>(3) Verify the uri can construct an image.</summary>
    public static bool CanCreateImageFrom(Uri uri)
    {
        try
        {
            var bm = new BitmapImage(uri);
            return bm.UriSource == uri;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e);
            return false;
        }
    }

I couldn't find a simple answer to this, so I wound up rolling my own code to accomplish three things with respect to image resources:
(1) have a string representation of a pack uri (databind)
(2) verify that the image is located where I think it is located (unit test)
(3) verify that the pack uri can be used to set an image (unit test)

Part of the reason this isn't simple is because pack uri's are a bit confusing at first, and come in several flavors. This code is for a pack uri that represents an image that is included in a VS assembly (either locally or a referenced assembly with a build action of 'resource'. This msdn articles clarifies what that means in this context. You also need to understand more about assemblies and builds than might initially seem like a good time.

Hope this makes it easier for someone else. Cheers,
Berryl

    /// <summary> (1) Creates a 'Resource' pack URI .</summary>
    public static Uri CreatePackUri(Assembly assembly, string path, PackType packType)
    {
        Check.RequireNotNull(assembly);
        Check.RequireStringValue(path, "path");

        const string startString = "pack://application:,,,/{0};component/{1}";
        string packString;
        switch (packType)
        {
            case PackType.ReferencedAssemblySimpleName:
                packString = string.Format(startString, assembly.GetName().Name, path);
                break;
            case PackType.ReferencedAssemblyAllAvailableParts:
                // exercise for the reader
                break;
            default:
                throw new ArgumentOutOfRangeException("packType");
        }
        return new Uri(packString);
    }

    /// <summary>(2) Verify the resource is located where I think it is.</summary>
    public static bool ResourceExists(Assembly assembly, string resourcePath)
    {
        return GetResourcePaths(assembly).Contains(resourcePath.ToLowerInvariant());
    }

    public static IEnumerable<object> GetResourcePaths(Assembly assembly, CultureInfo culture)
    {
        var resourceName = assembly.GetName().Name + ".g";
        var resourceManager = new ResourceManager(resourceName, assembly);

        try
        {
            var resourceSet = resourceManager.GetResourceSet(culture, true, true);

            foreach (DictionaryEntry resource in resourceSet)
            {
                yield return resource.Key;
            }
        }
        finally
        {
            resourceManager.ReleaseAllResources();
        }
    }

    /// <summary>(3) Verify the uri can construct an image.</summary>
    public static bool CanCreateImageFrom(Uri uri)
    {
        try
        {
            var bm = new BitmapImage(uri);
            return bm.UriSource == uri;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e);
            return false;
        }
    }
冷夜 2024-09-12 00:20:08
Public Class Res

    Private Shared __keys As New List(Of String)

    Shared Function Exist(partName As String) As Boolean
        Dim r As Boolean = False

        If __keys.Count < 1 Then
            Dim a = Assembly.GetExecutingAssembly()
            Dim resourceName = a.GetName().Name + ".g"
            Dim resourceManager = New ResourceManager(resourceName, a)
            Dim resourceSet = resourceManager.GetResourceSet(Globalization.CultureInfo.CurrentCulture, True, True)
            For Each res As System.Collections.DictionaryEntry In resourceSet
                __keys.Add(res.Key)
            Next
        End If

        __keys.ForEach(Sub(e)
                           If e.Contains(partName.ToLower) Then
                               r = True
                               Exit Sub
                           End If
                       End Sub)

        Return r
    End Function
End Class
Public Class Res

    Private Shared __keys As New List(Of String)

    Shared Function Exist(partName As String) As Boolean
        Dim r As Boolean = False

        If __keys.Count < 1 Then
            Dim a = Assembly.GetExecutingAssembly()
            Dim resourceName = a.GetName().Name + ".g"
            Dim resourceManager = New ResourceManager(resourceName, a)
            Dim resourceSet = resourceManager.GetResourceSet(Globalization.CultureInfo.CurrentCulture, True, True)
            For Each res As System.Collections.DictionaryEntry In resourceSet
                __keys.Add(res.Key)
            Next
        End If

        __keys.ForEach(Sub(e)
                           If e.Contains(partName.ToLower) Then
                               r = True
                               Exit Sub
                           End If
                       End Sub)

        Return r
    End Function
End Class
枯叶蝶 2024-09-12 00:20:08

我知道,这个问题很老了,但也许有人也有同样的问题。
我还遇到了一个问题,我想在单元测试中测试我的资源字符串。

最简单的解决方案是初始化 ResourceDictionary。您还可以使用dictionary.Keys["myKey"]访问特定键并检查内容。

[SetUp]
public void OnTestInitialize()
{
    if (!UriParser.IsKnownScheme("pack"))
    {
       new Application();
    }
}

[TestCase]
public void TestIfResourcesExist()
{
    var resources = new [] {
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonColors.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonStyles.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/GridSplitterStyle.xaml"
    };

    foreach (var mergedResource in resources)
    {
        // init
        ResourceDictionary dictionary =
            new ResourceDictionary {Source = new Uri(mergedResource, UriKind.RelativeOrAbsolute)};

        // verify
        dictionary.Keys.Count.Should().BeGreaterThan(0);
    }
}


顺便说一下,这是我在 App.xaml.cs 中注册资源的方式(这样我就可以在每个单元测试中测试它们):

public static class ResourceManager
{
    public static readonly string[] MergedResources = {
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonColors.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonStyles.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/GridSplitterStyle.xaml"
    };

    public static void AddResources()
    {
        Application.Current.Resources.BeginInit();
        foreach (var resource in MergedResources)
        {
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri(resource, UriKind.Absolute)
            });
        }
        Application.Current.Resources.EndInit();
    }
}

在 OnStartup 中:

// add xaml resources (styles, colors, ...)
ResourceManager.AddResources();

I know, the question is very old, but maybe someone has the same problem.
I also had the problem that I wanted to test my resource strings in a unit test.

The simplest solution is to initialize a ResourceDictionary. You can also access a specific key with dictionary.Keys["myKey"] and check the content.

[SetUp]
public void OnTestInitialize()
{
    if (!UriParser.IsKnownScheme("pack"))
    {
       new Application();
    }
}

[TestCase]
public void TestIfResourcesExist()
{
    var resources = new [] {
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonColors.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonStyles.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/GridSplitterStyle.xaml"
    };

    foreach (var mergedResource in resources)
    {
        // init
        ResourceDictionary dictionary =
            new ResourceDictionary {Source = new Uri(mergedResource, UriKind.RelativeOrAbsolute)};

        // verify
        dictionary.Keys.Count.Should().BeGreaterThan(0);
    }
}


By the way, this is the way I register my resources in the App.xaml.cs (so i can test them per unit test):

public static class ResourceManager
{
    public static readonly string[] MergedResources = {
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonColors.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/CommonStyles.xaml",
        "pack://application:,,,/Tracto.UI.Infrastructure;component/Dictionaries/GridSplitterStyle.xaml"
    };

    public static void AddResources()
    {
        Application.Current.Resources.BeginInit();
        foreach (var resource in MergedResources)
        {
            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
            {
                Source = new Uri(resource, UriKind.Absolute)
            });
        }
        Application.Current.Resources.EndInit();
    }
}

And in OnStartup:

// add xaml resources (styles, colors, ...)
ResourceManager.AddResources();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文