La réflexion est le plus couramment utilisé pour contourner le système de type statique, mais il a aussi quelques intéressantes cas d'utilisation:
Nous allons écrire un ORM!
Si vous êtes familier avec NHibernate ou la plupart des autres Orm, vous écrire des classes qui correspondent à des tables dans votre base de données, quelque chose comme ceci:
// used to hook into the ORMs innards
public class ActiveRecordBase
{
public void Save();
}
public class User : ActiveRecordBase
{
public int ID { get; set; }
public string UserName { get; set; }
// ...
}
Comment pensez-vous que l' Save()
méthode qui est écrit? Ainsi, dans la plupart des Orm, la méthode Save ne sais pas quels sont les champs dans les classes dérivées, mais il peut accéder à l'aide de la réflexion.
Sa filiale possible d'avoir les mêmes fonctionnalités dans un type de la sécurité, tout simplement par l'intervention d'un utilisateur de remplacer une méthode pour copier des champs dans un objet datarow, mais qui aurait pour résultat beaucoup de code réutilisable et le ballonnement.
Les talons!
Rhino se moque de est un moqueur cadre. Vous passez d'un type d'interface dans une méthode, et derrière les coulisses, le cadre construire de façon dynamique et instancier un objet fantaisie la mise en œuvre de l'interface.
Bien sûr, un programmeur peut écrire du code réutilisable pour la maquette de l'objet à la main, mais pourquoi serait-elle si le cadre va le faire pour elle?
Les métadonnées!
Nous pouvons décorer les méthodes avec des attributs (métadonnées), qui peuvent servir à diverses fins:
[FilePermission(Context.AllAccess)] // writes things to a file
[Logging(LogMethod.None)] // logger doesn't log this method
[MethodAccessSecurity(Role="Admin")] // user must be in "Admin" group to invoke method
[Validation(ValidationType.NotNull, "reportName")] // throws exception if reportName is null
public void RunDailyReports(string reportName) { ... }
Vous avez besoin de réfléchir sur la méthode d'inspecter les attributs. La plupart des AOP de cadres de .NET utiliser des attributs pour la politique de l'injection.
Bien sûr, vous pouvez écrire le même genre de code en ligne, mais ce style est plus déclaratif.
Nous allons faire un dépendance!
De nombreux Cio conteneurs exigent un certain degré de réflexion pour fonctionner correctement. Par exemple:
public class FileValidator
{
public FileValidator(ILogger logger) { ... }
}
// client code
var validator = IoC.Resolve<FileValidator>();
Notre conteneur IoC va instancier un fichier de programme de validation et de passer à une mise en œuvre appropriée de ILogger dans le constructeur. Quelle mise en œuvre? Tout dépend de ce que sa mise en œuvre.
Disons que j'ai donné le nom de l'assemblée et de la classe dans un fichier de configuration. La langue a besoin de lire le nom de la classe comme une chaîne de caractères et utiliser la réflexion pour l'instancier.
Si nous ne savons la mise en œuvre au moment de la compilation, il n'y a pas de type de moyen sûr d'instancier une classe basée sur son nom.
La Liaison Tardive / Duck-Typing
Il y a toutes sortes de raisons pourquoi vous voulez lire les propriétés d'un objet lors de l'exécution. Je choisirais l'exploitation forestière comme l'utilisation la plus simple, disons que vous avez écrit un enregistreur qui accepte n'importe quel objet et crache toutes ses propriétés d'un fichier.
public static void Log(string msg, object state) { ... }
Vous pourriez remplacer la méthode Log pour tous les types statiques, ou vous pouvez simplement utiliser la réflexion pour lire les propriétés de la place.
Certains langages comme OCaml et de la Scala de soutien de manière statique vérifié duck-typing (appelé structurels de frappe), mais parfois vous n'avez tout simplement pas le temps de compilation des connaissances de l'un des objets de l'interface.
Ou que les programmeurs Java savez, parfois, le type de système de votre chemin et vous obligent à écrire toutes sortes de code réutilisable. Il y a un article bien connu qui explique comment de nombreux modèles de conception sont simplifiées grâce au typage dynamique.
Parfois contourner le type de système permet de restructurer le code vers le bas beaucoup plus loin que ce qui est possible avec les types statiques, résultant en un peu plus propre code (de préférence caché derrière un sympathique programmeur API :) ). De nombreux statique modernes langues sont l'adoption de la règle d'or "typage statique, si possible, typage dynamique si nécessaire", permettant à des utilisateurs de commuter entre statique et dynamique de code.