Mar*_*tin 22 .net c# embedded-resource
我有一个可移植的库,我用于Windows Phone应用程序.在同一个可移植库中,我有几个内容文件(Build Action = Content).
我DataReader在Portable Library中创建了一个类,它应该向我返回一个流到内容文件.然而,下面的代码我一直取回null的GetManifestResourceStream.我究竟做错了什么?
public class DataReader
{
public static Stream GetStream(string code)
{
string path = string.Format("./data/code-{0}.dat", code);
return Assembly.GetExecutingAssembly().GetManifestResourceStream(path);
}
}
Run Code Online (Sandbox Code Playgroud)
And*_*ott 36
你的道路是错的.您正在使用斜杠,但在嵌入式清单资源名称中,斜杠在构建期间转换为句点.此外,根据您的PCL目标平台,您甚至可能无法打电话Assembly.GetExecutingAssembly().
这是你可以做的:
var assembly = typeof(AnyTypeInYourAssembly).GetTypeInfo().Assembly;
// Use this help aid to figure out what the actual manifest resource name is.
string[] resources = assembly.GetManifestResourceNames();
// Once you figure out the name, pass it in as the argument here.
Stream stream = assembly.GetManifestResourceStream("Some.Path.AndFileName.Ext");
Run Code Online (Sandbox Code Playgroud)
无法在Windows应用商店应用和Windows Phone 8应用之间轻松进行文件访问.您必须使用特定于平台的代码,才能打开文件并获取流.然后,您可以将流传递到PCL.
如果使用内容构建操作构建它,则XML不在DLL内部.它在文件系统上,并且没有办法从PCL内部获取它.这就是为什么所有答案都将构建操作设置为嵌入式资源的原因.它将文件放在里面MyPCL.DLL\Path\To\Content.xml.
但是,如果将构建操作设置为" 内容"并将复制类型设置为" 复制"(如果较新),则会将文件放在与可执行文件相同的目录中.

因此,我们可以在我们的PCL中放置一个用于读取文件的界面.在启动我们的非便携代码时,我们将一个实现注入PCL.
namespace TestPCLContent
{
public interface IContentProvider
{
string LoadContent(string relativePath);
}
}
namespace TestPCLContent
{
public class TestPCLContent
{
private IContentProvider _ContentProvider;
public IContentProvider ContentProvider
{
get
{
return _ContentProvider;
}
set
{
_ContentProvider = value;
}
}
public string GetContent()
{
return _ContentProvider.LoadContent(@"Content\buildcontent.xml");
}
}
}
Run Code Online (Sandbox Code Playgroud)
既然上面已经定义了PCL,我们可以在不可移植的代码中创建我们的接口实现(下面):
namespace WPFBuildContentTest
{
class ContentProviderImplementation : IContentProvider
{
private static Assembly _CurrentAssembly;
private Assembly CurrentAssembly
{
get
{
if (_CurrentAssembly == null)
{
_CurrentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
}
return _CurrentAssembly;
}
}
public string LoadContent(string relativePath)
{
string localXMLUrl = Path.Combine(Path.GetDirectoryName(CurrentAssembly.GetName().CodeBase), relativePath);
return File.ReadAllText(new Uri(localXMLUrl).LocalPath);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在应用程序启动时,我们注入实现,并演示加载内容.
namespace WPFBuildContentTest
{
//App entrance point. In this case, a WPF Window
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ContentProviderImplementation cpi = new ContentProviderImplementation();
TestPCLContent.TestPCLContent tpc = new TestPCLContent.TestPCLContent();
tpc.ContentProvider = cpi; //injection
string content = tpc.GetContent(); //loading
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:为简单起见,我保留了字符串而不是Streams.
如果您已将文件添加为资源,请检查您的.Designer.cs,每个资源都会有一个属性。您可以从中访问。
这是 dat 文件资源的示例自动生成属性
internal static byte[] MyDatFile {
get {
object obj = ResourceManager.GetObject("MyDatFile", resourceCulture);
return ((byte[])(obj));
}
Run Code Online (Sandbox Code Playgroud)
您可以将 dat 文件读取为
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
var str = enc.GetString(Resource1.MyDatFile);
Run Code Online (Sandbox Code Playgroud)