J'essaie de générer un PropertyGrid avec un objet généré dynamiquement.Impossible de créer correctement GenerA CustomAttributeData lors de l'utilisation de Enum généré par programme
Pour les sélections de combo sur cette grille de la propriété, j'ai construit un TypeConverter (où T est un ENUM, la définition de la liste des options):
public class TypedConverter<T> : StringConverter where T : struct, IConvertible
{
...
public override System.ComponentModel.TypeConverter.StandardValuesCollection
GetStandardValues(ITypeDescriptorContext context)
{
if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");
string[] values = Enum.GetValues(typeof(T)).OfType<object>().Select(o => o.ToString()).ToArray();
return new StandardValuesCollection(values);
}
}
je peux alors ajouter un attribut personnalisé à la propriété, référencement ce TypeConverter, comme ci-dessous (typedConverterGenericType est le type de TypedConverter avec un argument générique ENUM)
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(typeof(TypeConverterAttribute).GetConstructor(new Type[] { typeof(Type) }), new Type[] { typedConverterGenericType });
propertyBuilder.SetCustomAttribute(attributeBuilder);
cela fonctionne grand, tant que le Enum en question est hardcoded: AddTypeConverterAttribute(propertyBuilder, typeof(TypedConverter<Fred>));
. Dans le débogueur, l'attribut sur la propriété me donne {[System.ComponentModel.TypeConverterAttribute(...
.
Cependant, lorsque j'utilise un ENUM dynamique construit (que j'ai déterminé est généré correctement dans la réflexion) ne fonctionne pas:
Type enumType = enumBuilder.CreateType();//This generates a proper enum, as I have determined in reflection
Type converterType = typeof(TypedConverter<>);
Type typedConverterType = converterType.MakeGenericType(enumType);
AddTypeConverterAttribute(propertyBuilder, typedConverterType);
Dans le débogueur, l'attribut sur la propriété me donne maintenant {System.Reflection.CustomAttributeData}
, et forage dans ce, j'ai une erreur sur le ConstructorArguments ... Mscorlib_CollectionDebugView<System.Reflection.CustomAttributeData>(type.GetProperties()[1].CustomAttributes).Items[4].ConstructorArguments' threw an exception of type 'System.IO.FileNotFoundException'
Qu'est-ce que je fais mal? Comment puis-je obtenir l'attribut TypeConverter correctement?
EDIT: Dans le cas où quelqu'un veut voir comment ajouter l'attribut
private void AddTypeConverterAttribute(PropertyBuilder propertyBuilder, Type typedConverterGenericType)
{
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(typeof(TypeConverterAttribute).GetConstructor(new Type[] { typeof(Type) }), new Type[] { typedConverterGenericType });
propertyBuilder.SetCustomAttribute(attributeBuilder);
}
EDIT2
test confirme qu'il est un problème avec le ENUM dynamiquement construit - si je crée le générique tapez avec Type typedConverterType = converterType.MakeGenericType(typeof(Fred));
cela fonctionne bien.
EDIT 3
Mon projet de test est disponible here. Il lit un certain JSON de Resouces, et essaie de générer une classe dont le type est décrit par ce JSON.
Je crée une instance de cette classe (Activator.CreateInstance
) qui va générer un PropertyGrid. Pour obtenir la sélection de liste déroulante sur ce PropertyGrid, je crée un type, avec une propriété attribuée à TypedConverter, où T est une énumération qui décrit les valeurs dans la sélection de liste déroulante.
Cela fonctionne très bien pour les énumérations hardcoded, mais pas pour les
Avez-vous essayé 'publique EnumBuilder DefineEnum (nom de chaîne , TypeAttribute la visibilité, Type de type sous-jacent); 'dans' System.Reflection.Emit.ModuleBuilder'? Voici un exemple: https://msdn.microsoft.com/en-us/library/system.reflection.emit.enumbuilder(v=vs.110).aspx – mrtig
@mrtig Oui, je ne l'ai pas inclus pour des raisons de concision Saké. 'Builder EnumBuilder = moduleBuilder.DefineEnum (nom, TypeAttributes.Public, typeof (int));' est comment je reçois mon enumBuilder. – johnc