好的,这里是这样的:我有在C#中工作的代码,但是当我从PowerShell调用它时,它会失败。我不太清楚,但这是PowerShell特有的东西。下面是从C#调用库的相关代码(假设您提前添加了一个引用):
public class Test {
[STAThread]
public static void Main()
{
Console.WriteLine( PoshWpf.XamlHelper.RoundTripXaml(
"<TextBlock Text=\"{Binding FullName}\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>"
) );
}
}编译成可执行文件,很好.但是,如果您从PowerShell调用该方法,它将返回文本不带{Binding FullName}!
add-type -path .\PoshWpf.dll
[PoshWpf.Test]::Main()我已经粘贴到库的整个代码下面,所有代码都封装在一个PowerShell添加类型调用中,所以您只需将其粘贴到PowerShell中就可以编译它(如果您想将第一行和最后一行粘贴到Visual中的一个新控制台应用程序中)。
要作为可执行文件输出(从PowerShell 2),只需将-OutputType参数更改为ConsoleApplication,将-OutputAssembly更改为PoshWpf.exe (或其他东西)即可。因此,您可以看到,从可执行文件中运行相同的代码将为您提供正确的输出。
但是,运行上面这两行代码或者从[PoshWpf.XamlHelper]::RoundTripXaml [PoshWpf.XamlHelper]::ConvertToXaml 手动调用或似乎根本不起作用. HELP?!
Add-Type -TypeDefinition @"
using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace PoshWpf
{
public class Test {
[STAThread]
public static void Main()
{
Console.WriteLine( PoshWpf.XamlHelper.RoundTripXaml(
"<TextBlock Text=\"{Binding FullName}\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>"
) );
}
}
public class BindingTypeDescriptionProvider : TypeDescriptionProvider
{
private static readonly TypeDescriptionProvider _DEFAULT_TYPE_PROVIDER = TypeDescriptor.GetProvider(typeof(Binding));
public BindingTypeDescriptionProvider() : base(_DEFAULT_TYPE_PROVIDER) { }
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
ICustomTypeDescriptor defaultDescriptor = base.GetTypeDescriptor(objectType, instance);
return instance == null ? defaultDescriptor : new BindingCustomTypeDescriptor(defaultDescriptor);
}
}
public class BindingCustomTypeDescriptor : CustomTypeDescriptor
{
public BindingCustomTypeDescriptor(ICustomTypeDescriptor parent) : base(parent) { }
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
PropertyDescriptor pd;
var pdc = new PropertyDescriptorCollection(base.GetProperties(attributes).Cast<PropertyDescriptor>().ToArray());
if ((pd = pdc.Find("Source", false)) != null)
{
pdc.Add(TypeDescriptor.CreateProperty(typeof(Binding), pd, new Attribute[] { new DefaultValueAttribute("null") }));
pdc.Remove(pd);
}
return pdc;
}
}
public class BindingConverter : ExpressionConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return (destinationType == typeof(MarkupExtension)) ? true : false;
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(MarkupExtension))
{
var bindingExpression = value as BindingExpression;
if (bindingExpression == null) throw new Exception();
return bindingExpression.ParentBinding;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
public static class XamlHelper
{
static XamlHelper()
{
// this is absolutely vital:
TypeDescriptor.AddProvider(new BindingTypeDescriptionProvider(), typeof(Binding));
TypeDescriptor.AddAttributes(typeof(BindingExpression), new Attribute[] { new TypeConverterAttribute(typeof(BindingConverter)) });
}
public static string RoundTripXaml(string xaml)
{
return XamlWriter.Save(XamlReader.Parse(xaml));
}
public static string ConvertToXaml(object wpf)
{
return XamlWriter.Save(wpf);
}
}
}
"@ -language CSharpVersion3 -reference PresentationCore, PresentationFramework, WindowsBase -OutputType Library -OutputAssembly PoshWpf.dll同样,只需修改最后一行就可以得到一个可执行文件,如下所示:
"@ -language CSharpVersion3 -reference PresentationCore, PresentationFramework, WindowsBase -OutputType ConsoleApplication -OutputAssembly PoshWpf.exe发布于 2013-11-14 16:40:35
经过这么长一段时间(考虑到这个问题有多少视图),值得再次注意的是,这是固定的PowerShell 3中的 --我不确定这是因为他们修复了一个bug,还是因为PS3运行在.Net CLR 4上或什么的。
无论如何,如果将System.Xaml添加到-reference程序集列表中,那么原始问题中的代码将与PowerShell 3和4中的代码一样工作。
发布于 2010-03-23 14:56:07
我不是powershell dev,但您是否尝试过用`来转义{}?也许它是想变得聪明,并将绑定评估为一个powershell表达式?
发布于 2010-03-23 17:11:18
我对您在XamlHelper的类型初始化器中所做的TypeConverter设置有点困惑。BindingConverter应该做什么?您是否打算按照它在WPF中通常处理的方式处理{Binding}标记扩展?
在任何情况下,标记扩展都不能通过设计的XAML往返。以下摘录自有关XAML序列化限制的MSDN页面
序列化过程将取消对由各种标记扩展格式(如StaticResource或Binding )生成的对象的常见引用。在应用程序运行时创建内存中的对象时,它们已经被取消引用,而且Save逻辑不会重新访问原始的XAML来恢复对序列化输出的引用。这可能会冻结任何数据库或资源获取的值,使其成为运行时表示的最后一次使用的值,仅具有有限的或间接的能力来区分此值与本地任何其他值集。图像也被序列化为对项目中存在的图像的对象引用,而不是原始源引用,从而丢失了最初引用的任何文件名或URI。即使在同一页中声明的资源也会被序列化到被引用的位置,而不是作为资源集合的键保存下来。
考虑到这一点,我不知道为什么它应该在编译的应用程序中工作。但是正如我所说的,我必须承认我不知道你在用TypeConverter做什么,所以也许你已经解决了上面的限制。
https://stackoverflow.com/questions/2486076
复制相似问题