मेरे एमरल्ड डेटा फाउंडेशन (ईडीएफ) टूल में मैंने एक्स से अधिक शक्तिशाली मार्कअप एक्सटेंशन बनाकर इसे हल किया: टाइप जो सामान्य प्रकार भी निर्दिष्ट कर सकता है। इस तरह मैं लिख सकते हैं:
<DataTemplate TargetType="{edf:Type generic:ICollection{local:Entity}}" />
यहाँ मैं क्या इस्तेमाल किया है:
[MarkupExtensionReturnType(typeof(Type))]
public class TypeExtension : MarkupExtension
{
public TypeExtension() { }
public TypeExtension(string typeName) { TypeName = typeName; }
public TypeExtension(Type type) { Type = type; }
public string TypeName { get; set; }
public Type Type { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if(Type==null)
{
IXamlTypeResolver typeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
if(typeResolver==null) throw new InvalidOperationException("EDF Type markup extension used without XAML context");
if(TypeName==null) throw new InvalidOperationException("EDF Type markup extension used without Type or TypeName");
Type = ResolveGenericTypeName(TypeName, (name) =>
{
Type result = typeResolver.Resolve(name);
if(result==null) throw new Exception("EDF Type markup extension could not resolve type " + name);
return result;
});
}
return Type;
}
public static Type ResolveGenericTypeName(string name, Func<string, Type> resolveSimpleName)
{
if(name.Contains('{'))
name = name.Replace('{', '<').Replace('}', '>'); // Note: For convenience working with XAML, we allow {} instead of <> for generic type parameters
if(name.Contains('<'))
{
var match = _genericTypeRegex.Match(name);
if(match.Success)
{
Type[] typeArgs = (
from arg in match.Groups["typeArgs"].Value.SplitOutsideParenthesis(',')
select ResolveGenericTypeName(arg, resolveSimpleName)
).ToArray();
string genericTypeName = match.Groups["genericTypeName"].Value + "`" + typeArgs.Length;
Type genericType = resolveSimpleName(genericTypeName);
if(genericType!=null && !typeArgs.Contains(null))
return genericType.MakeGenericType(typeArgs);
}
}
return resolveSimpleName(name);
}
static Regex _genericTypeRegex = new Regex(@"^(?<genericTypeName>\w+)<(?<typeArgs>\w+(,\w+)*)>$");
}
सामान्य प्रकार का नाम पार्सिंग कोड एक अलग विधि में है, क्योंकि यह भी EDF में कुछ अन्य कोड से प्रयोग किया जाता है। आप इसे सभी एक विधि में जोड़ सकते हैं।
स्रोत
2009-11-03 23:25:48