2009-06-12 7 views
0

J'essaie de faire une résolution de type à l'intérieur d'une extension de balisage WPF en utilisant le même espace de noms: la syntaxe StaticType.Property utilisée par StaticExtension. L'extension fonctionne correctement à l'exécution et dans le concepteur Visual Studio, mais elle échoue dans Expression Blend. Après un débogage, j'ai compris que l'échec se produisait dans un appel à IXamlTypeResolver.Resolve().IXAmlTypeResolver.Resolve échoue dans le mélange

// 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); 

Le problème est le service.Resolve (typeName) qui échoue, mais seulement dans le mélange.

Jetez un coup d'œil à l'extension statique avec réflecteur et le code que MS utilise ne semble pas très différent.

Cela ressemble à un problème de sécurité - mais j'ai même essayé de signer et GAC l'assemblage et il échoue toujours exactement la même chose.

Trempé.

Répondre

0

Le problème est que le concepteur utilise une implémentation complètement différente de l'exécution de WPF. Il y a un bogue sur Microsoft Connect pour ce problème.

J'ai écrit une solution de contournement pour ce problème qui résout votre problème particulier et pourrait être distribué avec WPF Guide de localisation.

J'ai créé une enveloppe appelée ExpressionWorkaroundServiceProvider qui peut être utilisé comme ceci:

// 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); 

La mise en œuvre du 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; 
     }   
    } 
} 

Ce résolu le problème pour moi. Ce n'est pas un substitut à une implémentation correcte de IXamlTypeResolver mais la localisation fonctionnera sur le concepteur.

Questions connexes