2009-06-12 14 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實現的替代品,但會使本地化工作在設計器上。