我有一个项目,我使用Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider
当我开始尝试使用wpf windows时,我的问题就出现了。
我能够编译内存中的程序集,但是当我打开窗口时,我得到:
System.Exception:组件' Dynamic.DragonListForm'不具有 由URI标识的资源 ' /脚本代码;组件/ wpf_ui / dragonlistform.xaml&#39 ;. 在System.Windows.Application.LoadComponent(对象组件,Uri resourceLocator)
注意:我通过添加特定文件夹中所有.cs文件的列表进行编译
objCompileResults = objCodeCompiler.CompileAssemblyFromFile( objCompilerParameters, files.ToArray() );
我还添加了使其工作所需的dll引用。
注意:感谢Reed,我能够通过以下方式让它满足我的需求:
List<string> bamlFiles = Directory.GetFiles( directoryPath, "*.baml", SearchOption.AllDirectories ).ToList();
bamlFiles.ForEach( x => objCompilerParameters.EmbeddedResources.Add( x ) );
在我的项目中,这已经足够了。我有一个用于执行语音命令的.NET应用程序。一般来说,我有它所以我可以在更改语音命令时重新编译内存中的程序集更改。我想其中一些不能使用WPF,但我现在能够在内存中使用WPF窗口。
答案 0 :(得分:4)
问题是WPF文件不仅仅是C#,它们也是XAML,然后在单独的MSBuild任务中编译成BAML资源并作为嵌入资源包含。
如果您想支持某些版本,则需要将所有引用的xaml作为资源包含在内。有关如何使用CodeDom执行此操作的详细信息,请参阅this post。
完成后,您还必须确保使用兼容机制来加载类型。 C#编译xaml / xaml.cs文件的“正常”方式在您的情况下不起作用,因为它需要将资源预编译为baml。您必须有效地“重写”C#类型背后的代码,以使用不同的加载XAML的机制 - 通常这可以通过使用XamlObjectReader
和XamlObjectWriter
来读取xaml内容和在InitializeComponent
传递过程中“将它们写入”对象。
答案 1 :(得分:0)
另一个非常有用的信息是:The component does not have a resource identified by the uri
由此我创建了一个可以这样调用的扩展方法:
// https://stackoverflow.com/questions/7646331/the-component-does-not-have-a-resource-identified-by-the-uri
this.LoadViewFromUri( @"/ScriptCode;component/wpf_ui/spywindowviewer.xaml" );
// InitializeComponent();
注意:我只是使用显示在错误消息中的uri,例如:
组件&#39; Dynamic.DragonListForm&#39;没有由URI &#39; / ScriptCode; component / wpf_ui / dragonlistform.xaml&#39; 标识的资源。在
扩展方法:
using System;
using System.IO.Packaging;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Navigation;
namespace Extensions
{
public static class WpfWindowExtensions
{
// https://stackoverflow.com/questions/7646331/the-component-does-not-have-a-resource-identified-by-the-uri
public static void LoadViewFromUri( this Window window, string baseUri )
{
try
{
var resourceLocater = new Uri( baseUri, UriKind.Relative );
// log.Info( "Resource locator is: ")
var exprCa = ( PackagePart )typeof( Application ).GetMethod( "GetResourceOrContentPart", BindingFlags.NonPublic | BindingFlags.Static ).Invoke( null, new object[] { resourceLocater } );
var stream = exprCa.GetStream();
var uri = new Uri( ( Uri )typeof( BaseUriHelper ).GetProperty( "PackAppBaseUri", BindingFlags.Static | BindingFlags.NonPublic ).GetValue( null, null ), resourceLocater );
var parserContext = new ParserContext
{
BaseUri = uri
};
typeof( XamlReader ).GetMethod( "LoadBaml", BindingFlags.NonPublic | BindingFlags.Static ).Invoke( null, new object[] { stream, parserContext, window, true } );
}
catch( Exception )
{
//log
}
}
}
}