J'ai un type et une interface et j'ai besoin de vérifier que le type implémente l'interface de manière abstraite.Comment vérifier si un type .NET implémente abstraitement certaines interfaces .NET?
Je me suis mis à écrire un code de force brute en utilisant Reflection et c'est plutôt moche.
Je me demande s'il existe un meilleur moyen que la mise en œuvre de la force brute que je suis en train de faire.
Des idées?
Merci.
EDIT
ai pas vérifié la mise en œuvre encore, mais le projet de code de la force brute ressemble à ceci:
public static bool IsAbstractInterfaceImplementation(Type someType, Type someInterface)
{
if (!someInterface.IsAssignableFrom(someType))
{
return false;
}
if (!someType.IsAbstract)
{
return false;
}
var m_interfaceMemberNames = someInterface.GetMembers().Select(m => m.Name).ToList();
// Make sure every interface member implementation is abstract.
foreach (var typeMember in someType.FindMembers(MemberTypes.Event | MemberTypes.Property | MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance, null, null))
{
if (m_interfaceMemberNames.Contains(typeMember.Name))
{
MethodInfo method;
// Make sure the ancestor member is abstract.
switch (typeMember.MemberType)
{
case MemberTypes.Event:
if (!IsAbstractImplementation(((EventInfo)typeMember).GetAddMethod()))
{
return false;
}
method = ((EventInfo)typeMember).GetRemoveMethod();
break;
case MemberTypes.Property:
method = ((PropertyInfo)typeMember).GetGetMethod();
default:
method = (MethodInfo)typeMember;
break;
}
if (!IsAbstractImplementation(method))
{
return false;
}
}
}
return true;
}
public static bool IsAbstractImplementation(MethodInfo methodInfo)
{
const MethodAttributes expectedAttributes =
MethodAttributes.Abstract |
MethodAttributes.Public |
MethodAttributes.NewSlot |
MethodAttributes.Virtual;
return (methodInfo.Attributes & expectedAttributes) == expectedAttributes;
}
Sans compiler je vois déjà un problème avec des propriétés, que le code a pour vérifier si l'interface définit getter et/ou setter et vérifie la bonne méthode (s), au lieu d'assumer aveuglément le getter. Quoi qu'il en soit, comme on peut le voir, le code est plutôt terne. Je me demande s'il y a une meilleure façon ...
EDIT 2
- Je tiens à souligner que c'est juste une mise en œuvre du projet, il fonctionne pour les cas simples et il est cassé pour plus ceux complexes, comme quand il y a des surcharges de méthodes ou des renames de méthode (je ne connais pas VB, donc je ne pensais même pas que c'était possible). Mais cela souligne le fait que cela demande beaucoup de travail pour bien faire les choses.
- Pourquoi voudrais-je une telle chose? Nous devons créer des types dynamiquement en utilisant Reflection.Emit en fonction de certaines métadonnées acquises dynamiquement. Le type dynamique généré implémente certaines interfaces, par exemple IDynamicObject, et peut dériver de certains types d'ancêtres. Ce type d'ancêtre est compilé statiquement. Jusqu'à récemment, le type ancêtre n'était pas autorisé à implémenter l'interface IDynamicObject. Étant donné une instance du type dynamique, il fallait explicitement le convertir en IDynamicObject pour accéder à ses méthodes (rappelez-vous que le type dynamique généré implémente l'interface). Je voudrais éliminer ces castes explicites. La seule façon de le faire est de laisser le type ancêtre implémenter l'interface IDynamicObject. Cependant, l'implémentation doit être entièrement abstraite, ce qui est vérifié par le code de création de type dynamique. Voila.
"code de force brute utilisant la réflexion" - pouvez-vous l'afficher? –
que voulez-vous dire exactement quand vous dites que le "type implémente l'interface abstraitement"? – LBushkin
OK, quelques minutes pour s'assurer que cela fonctionne du tout. – mark