【发布时间】:2013-03-05 14:08:39
【问题描述】:
我想从我的 ViewModel 代码访问存储在 WMAppManifest.xml 文件中的 Title 值。这与通过项目属性设置的应用程序标题相同。
有没有办法使用 App.Current 之类的代码从代码中访问它?
【问题讨论】:
标签: silverlight windows-phone-7 manifest
我想从我的 ViewModel 代码访问存储在 WMAppManifest.xml 文件中的 Title 值。这与通过项目属性设置的应用程序标题相同。
有没有办法使用 App.Current 之类的代码从代码中访问它?
【问题讨论】:
标签: silverlight windows-phone-7 manifest
查看the source code 中的Microsoft Silverlight Analytics Framework 中的WP7DataCollector.GetAppAttribute()。 GetAppAttribute("Title") 会做。
/// <summary>
/// Gets an attribute from the Windows Phone App Manifest App element
/// </summary>
/// <param name="attributeName">the attribute name</param>
/// <returns>the attribute value</returns>
private static string GetAppAttribute(string attributeName)
{
string appManifestName = "WMAppManifest.xml";
string appNodeName = "App";
var settings = new XmlReaderSettings();
settings.XmlResolver = new XmlXapResolver();
using (XmlReader rdr = XmlReader.Create(appManifestName, settings))
{
rdr.ReadToDescendant(appNodeName);
if (!rdr.IsStartElement())
{
throw new System.FormatException(appManifestName + " is missing " + appNodeName);
}
return rdr.GetAttribute(attributeName);
}
}
【讨论】:
这最后一个答案对我来说似乎过于复杂;您可以简单地执行以下操作:
string name = "";
var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var customAttributes = executingAssembly.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false);
if (customAttributes != null)
{
var assemblyName = customAttributes[0] as System.Reflection.AssemblyTitleAttribute;
name = assemblyName.Title;
}
【讨论】:
我已经使用 Michael S. Scherotter 他出色的代码示例将其制作成一个完全可以工作的代码示例:
using System.Xml;
namespace KoenZomers.WinPhone.Samples
{
/// <summary>
/// Allows application information to be retrieved
/// </summary>
public static class ApplicationInfo
{
#region Constants
/// <summary>
/// Filename of the application manifest contained within the XAP file
/// </summary>
private const string AppManifestName = "WMAppManifest.xml";
/// <summary>
/// Name of the XML element containing the application information
/// </summary>
private const string AppNodeName = "App";
#endregion
#region Properties
/// <summary>
/// Gets the application title
/// </summary>
public static string Title
{
get { return GetAppAttribute("Title"); }
}
/// <summary>
/// Gets the application description
/// </summary>
public static string Description
{
get { return GetAppAttribute("Description"); }
}
/// <summary>
/// Gets the application version
/// </summary>
public static string Version
{
get { return GetAppAttribute("Version"); }
}
/// <summary>
/// Gets the application publisher
/// </summary>
public static string Publisher
{
get { return GetAppAttribute("Publisher"); }
}
/// <summary>
/// Gets the application author
/// </summary>
public static string Author
{
get { return GetAppAttribute("Author"); }
}
#endregion
#region Methods
/// <summary>
/// Gets an attribute from the Windows Phone App Manifest App element
/// </summary>
/// <param name="attributeName">the attribute name</param>
/// <returns>the attribute value</returns>
private static string GetAppAttribute(string attributeName)
{
var settings = new XmlReaderSettings {XmlResolver = new XmlXapResolver()};
using (var rdr = XmlReader.Create(AppManifestName, settings))
{
rdr.ReadToDescendant(AppNodeName);
// Return the value of the requested XML attribute if found or NULL if the XML element with the application information was not found in the application manifest
return !rdr.IsStartElement() ? null : rdr.GetAttribute(attributeName);
}
}
#endregion
}
}
【讨论】:
在原始问题的范围内,只有前两个答案是正确的。第二个当然不是太复杂。用一个类为每个可能的属性包装辅助方法是很好的面向对象开发,这正是微软在整个框架中所做的,例如Visual Studio 生成的设置设计器文件。
如果您只想要一个特定的属性,我建议使用第一个,如果您想要更多,则建议使用第二个。真的应该是 SDK 的一部分。我们正在尝试在这里读取 WMAppManifest.xml 而不是 AssemblyInfo,因此标准程序集反射元数据不好。
顺便说一句,如果您真的想从程序集属性(而不是 WPAppManifest.xml)中获取产品名称,那么最后一个示例读取了错误的属性!使用 AssemblyProductAttribute 而不是 AssemblyTitleAttribute。程序集标题实际上是文件标题,默认情况下与程序集文件名相同(例如 MyCompany.MyProduct.WinPhone7App),而产品通常类似于商店中应用程序的正确格式的“标题”(例如“我的产品”)。使用 VS 属性页面后,它甚至可能不是最新的,所以你应该检查一下。
我对所有其他应用程序类型使用 AssemblyInfo 反射,以在 about 页面上显示官方产品名称和构建版本,这当然是正确的。但是对于这些特殊的手机应用类型,商店清单具有更多的重要性和您可能需要的其他属性。
【讨论】:
所有这些答案的问题在于,他们必须在每次访问文件时都读取文件。这对性能不利,因为如果您经常使用它,则需要考虑电池问题。 Koen 更接近于一个正确的解决方案,但他的设计仍然会在您每次想要访问该值时回到文件中。
以下解决方案是一次性读取文件。由于它不太可能改变,因此没有理由继续回到它。在初始化静态类时读取属性,非常简单。
I created this Gist to demonstrate.
HTH!
【讨论】: