2009-06-12 39 views
0

我正在尝试使用StaticExtension使用的相同名称空间:StaticType.Property语法在WPF标记扩展中执行某种类型的解析。该扩展在运行时和Visual Studio设计器中工作正常,但在Expression Blend中失败。经过一些调试后,我发现在调用IXamlTypeResolver.Resolve()时发生故障。IXAmlTypeResolver.Resolve在Blend中失败

// 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的大会,它仍然没有完全一样。

难倒。

回答

0

问题是设计师使用完全不同于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实现的替代品,但会使本地化工作在设计器上。