3

カスタム xaml 拡張機能を作成しましたが、設計時に IXamlTypeResolver を取得できません。私はいくつかのゴーグリングを行いましたが、これは dev studio 2010 で導入されたバグが原因のようです。実験として、x:Static を逆コンパイルし、外部拡張機能として再構築しましたが、IXamlTypeResolver も取得できません。ただし、ビルド 1 は設計時に機能します。何らかの内部魔法が起こっているに違いないと思います。回避策があるかどうか疑問に思っています。名前空間 xaml 宣言の解析など、必要な情報を取得するために追加の作業を行ってもかまいませんが、これを行うために必要なサービスも設計時に利用できないようです。Microsoft はこの問題を修正する予定はありますか? カスタム xaml 拡張機能の有用性が大幅に制限されます。これは、サード パーティのライブラリ プロバイダーに影響を与えるに違いありません。

[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