【发布时间】:2010-06-10 20:21:03
【问题描述】:
验证是否可以找到包 uri 的最简单方法是什么?
例如,给定
pack://application:,,,Rhino.Mocks;3.5.0.1337;0b3305902db7183f;component/SomeImage.png
如何检查图片是否真实存在?
干杯,
浆果
【问题讨论】:
验证是否可以找到包 uri 的最简单方法是什么?
例如,给定
pack://application:,,,Rhino.Mocks;3.5.0.1337;0b3305902db7183f;component/SomeImage.png
如何检查图片是否真实存在?
干杯,
浆果
【问题讨论】:
我找不到一个简单的答案,所以我最终滚动自己的代码来完成与图像资源相关的三件事:
(1) 有一个包 uri 的字符串表示(数据绑定)
(2) 验证图像是否位于我认为的位置(单元测试)
(3) 验证pack uri可以用来设置图片(单元测试)
这并不简单的部分原因是,pack uri 一开始有点令人困惑,而且有多种风格。此代码用于表示包含在 VS 程序集中的图像的包 uri(本地或具有“资源”构建操作的引用程序集。此 msdn articles 阐明了在此上下文中的含义。您还需要了解更多关于程序集和构建的信息,而不是最初看起来的好时机。
希望这对其他人来说更容易。干杯,
浆果
/// <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;
}
}
【讨论】:
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
【讨论】:
我知道,这个问题很老了,但也许有人有同样的问题。 我也有一个问题,我想在单元测试中测试我的资源字符串。
最简单的解决方案是初始化一个 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();
【讨论】: