Хорошо, вот в чем дело: у меня есть код, который работает на 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()
Я вставил ниже весь код библиотеки, завернутый в вызов Add-Type PowerShell, так что вы можете просто скомпилировать его, вставив в PowerShell (вы можете пропустить первую и последнюю строки, если хотите вставьте его в новое консольное приложение в Visual Studio.
Чтобы вывести (из PowerShell 2) в виде исполняемого файла, просто измените параметр -OutputType на ConsoleApplication и -OutputAssembly на PoshWpf.exe (или что-то еще). Таким образом, вы можете видеть, что запуск SAME CODE из исполняемого файла дает правильный вывод.
Но запуск двух строк, как указано выше, или ручной вызов [PoshWpf.XamlHelper]::RoundTripXaml
или [PoshWpf.XamlHelper]::ConvertToXaml
из PowerShell просто не работают вообще ... 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