Ошибка IXAmlTypeResolver.Resolve в Blend - PullRequest
0 голосов
/ 12 июня 2009

Я пытаюсь выполнить какое-то разрешение типов внутри расширения разметки WPF, используя то же пространство имен: синтаксис StaticType.Property, который использует StaticExtension. Расширение отлично работает во время выполнения, а также в конструкторе Visual Studio, но не работает в Expression Blend. После некоторой отладки я выяснил, что сбой происходит при вызове IXamlTypeResolver.Resolve ().

// Parse Static=properties:Resources.HelloWorld like static resource
int index = this.Static.IndexOf('.');
if (index == -1)
    throw new ArgumentException(Resources.InvalidStaticBindingSyntax + ": " + 
                                this.Static);

// resolve properties:Resources
string typeName = this.Static.Substring(0, index);
IXamlTypeResolver service = _serviceProvider.GetService(typeof(IXamlTypeResolver))
                            as IXamlTypeResolver;

Type memberType = service.Resolve(typeName);

string propName = this.Static.Substring(index + 1);
localized = memberType.GetProperty(propName,
                       BindingFlags.Public | 
                       BindingFlags.Static | 
                       BindingFlags.FlattenHierarchy)
                       .GetValue(memberType, null);

Проблема в том, что service.Resolve (typeName) не работает, но только в Blend.

Взглянул на StaticExtension с Reflector, и код, который использует MS, не сильно отличается.

Это похоже на проблему безопасности - но я даже пытался подписать и GAC сборку, и она все равно не работает.

Тупик.

1 Ответ

0 голосов
/ 11 января 2011

Проблема в том, что дизайнер использует реализацию, совершенно отличную от среды выполнения WPF. В Microsoft Connect есть ошибка для этой проблемы.

Я написал обходной путь для этой проблемы, который решает вашу конкретную проблему и может распространяться вместе с Руководством по локализации WPF.

Я создал оболочку под названием ExpressionWorkaroundServiceProvider, которую можно использовать следующим образом:

// resolve properties:Resources
string typeName = this.Static.Substring(0, index);
string propName = this.Static.Substring(index + 1);

IServiceProvider serviceProvider = new ExpressionWorkaroundServiceProvider(_serviceProvider)
{
    PropertyName = propName
};

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

Type memberType = service.Resolve(typeName);

this._propertyInfo = memberType.GetProperty(propName,
                BindingFlags.Public |
                BindingFlags.Static |
                BindingFlags.FlattenHierarchy |
                BindingFlags.NonPublic);

Реализация ExpressionWorkaroundServiceProvider:

internal class ExpressionWorkaroundServiceProvider : IServiceProvider, IXamlTypeResolver
{
    private IServiceProvider _originalProvider;

    public string PropertyName { get; set; }

    public ExpressionWorkaroundServiceProvider(IServiceProvider originalProvider)
    {
        if (originalProvider == null)
        {
            throw new ArgumentNullException("originalProvider");
        }

        _originalProvider = originalProvider;
    }

    public object GetService(Type serviceType)
    {
        var servicedObject = _originalProvider.GetService(serviceType);

        if (servicedObject == null && serviceType == typeof(IXamlTypeResolver))
        {
            return this;
        }

        return servicedObject;
    }

    public Type Resolve(string qualifiedTypeName)
    {
        var typeName = qualifiedTypeName.Substring(qualifiedTypeName.IndexOf(':') + 1);

        var types =
            AppDomain.CurrentDomain.GetAssemblies().Aggregate(new List<Type>(),
                (list, asm) =>
                {
                    list.AddRange(asm.GetTypes().Where(p => p.Name.Contains(typeName)));
                    return list;
                });

        if (string.IsNullOrWhiteSpace(PropertyName))
        {
            return types.FirstOrDefault();
        }
        else
        {
            foreach (var type in types)
            {
                if (type.GetProperty(PropertyName,
                        BindingFlags.Public |
                        BindingFlags.Static |
                        BindingFlags.FlattenHierarchy |
                        BindingFlags.NonPublic) != null)
                {
                    return type;
                }
            }

            return null;
        }           
    }
}

Это решило проблему для меня. Это не замена правильной реализации IXamlTypeResolver, но заставит локализацию работать на конструкторе.

...