2009-06-12 8 views
0

동일한 네임 스페이스를 사용하여 WPF Markup Extension 내부에서 유형 해상도를 시도하고 있습니다. StaticExtension이 사용하는 StaticType.Property 구문. 이 확장은 런타임과 Visual Studio 디자이너에서 잘 작동하지만 Expression Blend에서는 실패합니다. 일부 디버깅 후 IXamlTypeResolver.Resolve() 호출이 실패했음을 알았습니다.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을 살펴보면 MS가 사용하는 코드가 크게 달라 보이지 않습니다.

보안 문제처럼 보입니다.하지만 어셈블리에 서명하고 GAC를 시도했는데 여전히 정확하게 동일하지 않습니다.

Stumped.

답변

0

문제는 디자이너가 WPF 런타임과 완전히 다른 구현을 사용한다는 것입니다. 이 문제에 대한 Microsoft Connect의 버그가 있습니다.

이 문제의 해결 방법은 특정 문제를 해결하고 WPF Localization Guidance와 함께 배포 할 수있는 해결 방법을 작성했습니다.

나는이처럼 사용할 수 있습니다 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 구현을 대신 할 수는 없지만 디자이너에서 작동하는 지역화를 얻게됩니다.