3

我编写了一个自定义 xaml 扩展,但在设计时无法获得 IXamlTypeResolver。我做了一些观察,这似乎是由于 dev studio 2010 中引入的一个错误。作为实验,我反编译了 x:Static 并重建为外部扩展,但它也无法获得 IXamlTypeResolver。然而,构建一个在设计时工作。我想一定有一些内在的魔力在发生。我想知道是否有任何解决方法。我不介意做一些额外的工作来获取我需要的信息,比如解析命名空间 xaml 声明,但似乎我需要这样做的服务在设计时也不可用。Microsoft 是否有解决此问题的计划?它严重限制了自定义 xaml 扩展的实用性。这一定会影响到第 3 方库提供者——我想知道他们是如何解决这个问题的。

[MarkupExtensionReturnType(typeof(object))]
[TypeConverter(typeof(MyStaticExtensionConverter))]
public class MyStaticExtension : MarkupExtension
{
    private string _member;
    private Type _memberType;

    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    public MyStaticExtension()
    {
    }

    public MyStaticExtension(string member)
    {
        if (member == null) {
            throw new ArgumentNullException("member");
        }
        this._member = member;
    }

    private bool GetFieldOrPropertyValue(Type type, string name, out object value)
    {
        FieldInfo field = null;
        Type baseType = type;
        do {
            field = baseType.GetField(name, BindingFlags.Public | BindingFlags.Static);
            if (field != null) {
                value = field.GetValue(null);
                return true;
            }
            baseType = baseType.BaseType;
        }
        while (baseType != null);
        PropertyInfo property = null;
        baseType = type;
        do {
            property = baseType.GetProperty(name, BindingFlags.Public | BindingFlags.Static);
            if (property != null) {
                value = property.GetValue(null, null);
                return true;
            }
            baseType = baseType.BaseType;
        }
        while (baseType != null);
        value = null;
        return false;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (this._member == null) {
            throw new InvalidOperationException("MarkupExtensionStaticMember");
        }

        Type memberType = this.MemberType;
        string str = null;
        string str2 = null;
        object obj2;
        if (memberType != null) {
            str = this._member;
            str2 = memberType.FullName + "." + this._member;
        }
        else {
            str2 = this._member;
            int index = this._member.IndexOf('.');
            if (index < 0) {
                throw new ArgumentException("MarkupExtensionBadStatic", this._member);
            }

            string qualifiedTypeName = this._member.Substring(0, index);
            if (qualifiedTypeName == string.Empty) {
                throw new ArgumentException("MarkupExtensionBadStatic", this._member);
            }

            if (serviceProvider == null) {
                throw new ArgumentNullException("serviceProvider");
            }

            IXamlTypeResolver service = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;

            // Exception will thrown here as at design time
            if (service == null) {


                throw new ArgumentException("MarkupExtensionNoContext", base.GetType().Name);
            }

            memberType = service.Resolve(qualifiedTypeName);
            str = this._member.Substring(index + 1, (this._member.Length - index) - 1);
            if (str == string.Empty) {
                throw new ArgumentException("MarkupExtensionBadStatic", this._member);
            }
        }

        if (memberType.IsEnum) {
            return Enum.Parse(memberType, str);
        }

        if (!this.GetFieldOrPropertyValue(memberType, str, out obj2)) {
            throw new ArgumentException("MarkupExtensionBadStatic", str2);
        }

        return obj2;
    }

    [ConstructorArgument("member")]
    public string Member
    {
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        get
        {
            return this._member;
        }
        set
        {
            if (value == null) {
                throw new ArgumentNullException("value");
            }
            this._member = value;
        }
    }

    [DefaultValue((string)null)]
    public Type MemberType
    {
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        get
        {
            return this._memberType;
        }
        set
        {
            if (value == null) {
                throw new ArgumentNullException("value");
            }
            this._memberType = value;
        }
    }
}

internal class MyStaticExtensionConverter : TypeConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return ((destinationType == typeof(InstanceDescriptor)) || base.CanConvertTo(context, destinationType));
    }

    [SecurityCritical, SecurityTreatAsSafe]
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType != typeof(InstanceDescriptor)) {
            return base.ConvertTo(context, culture, value, destinationType);
        }

        MyStaticExtension extension = value as MyStaticExtension;
        if (extension == null) {
            throw new ArgumentException("MustBeOfType", "value");
        }

        return new InstanceDescriptor(typeof(MyStaticExtension).GetConstructor(new Type[] { typeof(string) }), new object[] { extension.Member });
    }
}
4

0 回答 0