2009-06-12 5 views
0

Ich versuche, einige Typauflösung innerhalb einer WPF-Markup-Erweiterung mit dem gleichen Namespace zu tun: StaticType.Property-Syntax, die StaticExtension verwendet. Die Erweiterung funktioniert zur Laufzeit und auch im Visual Studio-Designer, schlägt aber in Expression Blend fehl. Nach einigen Debugging habe ich herausgefunden, dass der Fehler in einem Aufruf von IXamlTypeResolver.Resolve() auftritt.IXAmlTypeResolver.Resolve fehlgeschlagen in 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); 

Das Problem ist der service.Resolve (typeName), die fehlschlägt, aber nur in Blend.

Wir haben uns die StaticExtension mit Reflector angesehen und der Code, den MS verwendet, sieht nicht viel anders aus.

Es sieht aus wie ein Sicherheitsproblem - aber ich habe sogar versucht, zu signieren und GAC die Assembly und es immer noch genau das gleiche fehlschlägt.

Stumped.

Antwort

0

Das Problem ist, dass der Designer eine vollständig andere Implementierung als WPF Laufzeit verwendet. Es gibt einen Fehler in Microsoft Connect für dieses Problem.

Ich habe eine Problemumgehung für dieses Problem geschrieben, das Ihr spezielles Problem löst und mit WPF Localization Guidance verteilt werden könnte.

habe ich einen Wrapper ExpressionWorkaroundServiceProvider genannt, die wie folgt verwendet werden kann:

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

Die Umsetzung des 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; 
     }   
    } 
} 

Dies das Problem für mich gelöst. Es ist kein Ersatz für eine korrekte IXamlTypeResolver-Implementierung, aber es wird die Lokalisierung für den Designer funktionieren.