J'ai deux objets du même type et j'ai besoin de copier des valeurs de propriété d'un objet à un autre. Il y a deux options:
Utilisez la réflexion, naviguez sur les propriétés du premier objet et copiez les valeurs. P> li>
sérialiser le premier objet et désérialiser une copie. p> li> ol>
Les deux travaux de mon exigence, la question est laquelle est la question que je ferais mieux d'utiliser dans les termes de la vitesse (coût)? p>
Exemple strong> p> xxx pré> besoin de copier des valeurs de propriété à partir de pour cet échantillon simple - quelle méthode est plus rapide? p> pour la sérialisation, j'utilise l'objetCIPER suggéré ici: Objets de clonage profond P> pour la réflexion J'utilise ce code: p> Personne P1 code> à
Personne P2 code>. p>
foreach (PropertyInfo sourcePropertyInfo in copyFromObject.GetType().GetProperties())
{
PropertyInfo destPropertyInfo = copyToObject.GetType().GetProperty(sourcePropertyInfo.Name);
destPropertyInfo.SetValue(
copyToObject,
sourcePropertyInfo.GetValue(copyFromObject, null),
null);
}
5 Réponses :
La sérialisation binaire est très rapide, je l'utilise beaucoup pour ce type de problème p>
Pour la sérialisation, j'utilise l'objetCopier à partir de ce fil, est-ce plus rapide que la réflexion?
@net_prog Comment pensez-vous que Binarinformatter code> (le sérialisateur sous
ObjectCopier code>) obtient ses données? Astuce: il commence par "R" et sonne comme "déviation".
Si vous copiez les propriétés pendant le temps d'exécution, la réflexion serait la solution. J'irais pour la sérialisation si ce n'est pas pendant la période d'exécution. sérialisation vs réflexion Regardez cette fois. P>
Si vous connaissez les propriétés de l'objet pendant le temps d'exécution, la réflexion serait une perte de temps, la sérialisation serait la solution. Mais si vous ne connaissez pas les propriétés de l'objet pendant le temps d'exécution, la réflexion est la seule solution que je puisse penser.
Si vous connaissez les propriétés, pourquoi la sérialisation serait-elle soudainement meilleure que la réflexion? Pas sûr que ça a du sens ...
Parce que la réflexion est utilisée lorsque le type d'objet n'est pas connu pendant l'exécution. Si le type d'objet est déjà connu, pourquoi prendre la peine d'utiliser la réflexion lorsque la sérialisation (sérialisation binaire) est rapide et facilement obtenue.
Cela n'a aucun sens. La sérialisation va impliquer une réflexion ici; L'ajout des étapes réelles du codage / décodage ajoute uniquement du travail. Pour deux implémentations raisonnables d'une série de réflexions-copieur vs, et pour une copie peu profonde, le copieur de réflexion est préférable à tous égards. Parlé comme une personne qui sait aussi énormément de la réflexion et de la sérialisation.
Tout dépend de ce que vous souhaitez copier et de quel type de sérialisateur vous envisagez d'utiliser. Chose avec des sérialiseurs est, certains em> d'entre eux pourraient être en train d'utiliser la réflexion comme mécanisme sous-jacent des objets de construction. Edit # 1: Strong> Autant que je sache, EDIT # 2: STRUT> SUR LA CURIOSITÉ, j'ai Exécuter un test simple. Quels sont les résultats par rapport à Je suppose que la différence provient du fait que code source pour le programme de test que j'ai utilisé peut être trouvé Ici . N'importe qui est bienvenue dans des défauts ponctuels et des problèmes possibles avec celui-ci: -) p> sidenote em> BinaryFormatter Code> utilisé par votre classe utilise la réflexion pour faire son travail. Donc, la question est, pouvez-vous écrire de mieux (plus rapide?) Code de réflexion personnalisé pour vos types que Microsoft a fait pour scénario général? P>
BinaryFormatter Code> VS Réflexion en termes d'exécution Copie peu profonde em>. Le code de réflexion que j'ai utilisé peut être vu ici: p>
ObjectCopier Code> Classe que vous utilisez? La réflexion semble exécuter
BinaryFormatter code> doit utiliser des flux, qui introduisent des frais généraux supplémentaires. Pourtant, ce n'est que mon hypothèse, qui pourrait être loin des faits. P>
Comme avec tous les "je me demandais ..." em> repères, je vous suggère de le prendre avec un grain de sel. Ces optimisations ne doivent être faites que lorsque leurs performances deviennent en réalité un problème. p> p>
J'ai des classes simples avec des types primitifs, tels que INT, String, etc. J'utilise Serializer suggéré ici: Stackoverflow.com/Questtions/78536/cloning-Objects-in-c-sharp Types de classes sont fournis par code externe.
@net_prog: vérifiez mon édition. J'ai exécuté un test simple pour votre classe en utilisant les deux méthodes.
Merci, c'est ce que je cherchais. En fait, je voulais vraiment que la classe soit avec des propriétés, pas des champs, j'ai corrigé l'échantillon. Mais même dans ce cas, la réflexion est plus rapide comme je peux voir.
En fin de compte, des sérialiseurs à usage général (tels que Puisque vous ne voulez que une copie peu profonde, un outil tel que FOWORAPPER est l'outil le plus approprié em> ici; Encore une fois, il utilise une réflexion (mais je m'attends à ce qu'elle le fait "de la bonne façon", c'est-à-dire non via Dans ce scénario, la sérialisation est surchargée; FOWERAPPER est parfaitement raisonnable. Si vous vouliez des clones profonds, il devient plus difficile ... La sérialisation peut commencer à être tentante. Je ne choisirais toujours pas Ce serait bien sûr trivial à droite de la réflexion em> de base em> qui fait la même chose via Binarinformatter code>, via
ObjectCopier code>) utilise la réflexion forte>. Comment bien em> ils utilisent cela dépend du sérialiseur spécifique, mais il y a toujours des frais généraux supplémentaires impliqués si vous êtes sérialisé. P>
getvalue () code> /
SETValue () code>), mais ça ne " t avoir les coûts de sérialisation. P>
binarinformatter code> moi-même, mais je suis très difficile à propos de la sérialisation; p p>
getvalue () code> etc., mais ce serait lent. Une autre option intéressante ici est que vous pouvez utiliser l'API CODE> EXPRESSE CODE> pour créer un copieur d'objet au moment de l'exécution ... mais ... FOWNAPPER fait tout ce dont vous auriez besoin ici, alors cela semble donc des efforts redondants. < / p>
void Copy(object copyToObject, object copyFromObject) { BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; FieldInfo[] fields = copyFromObject.GetType().GetFields(flags); for (int i = 0; i < fields.Length; ++i) { BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; FieldInfo field = copyFromObject.GetType().GetField(fields[i].Name, bindFlags); FieldInfo toField = copyToObject.GetType().GetField(fields[i].Name, bindFlags); if(field != null) { toField.SetValue(copyToObject, field.GetValue(copyFromObject)); } } }
Le code pourrait répondre à la question. Mais vous aidez la puissance plus si vous expliquez ce que le code fait et comment cela résout la question.
Que diriez-vous de Automapper Automapper.org ou simplement cloner () faire le travail?
Pourquoi ne pouvez-vous pas le faire avec une affectation normale?
@Miau, cela semble être un système de copie de la propriété complexe, merci pour le lien, très intéressant. Mais pour mon besoin actuellement, j'essaye que cela soit simple, afin que SOPApper soit un canon pour ce cas, je pense. Mais je vais certainement l'examiner et l'utiliser pour des tâches complexes.
@DavidKemP, car ce doit être un système universel qui fonctionne pour toutes les classes fournies.
@net_prog alors voulez-vous une copie profonde ou peu profonde?
@DAVIDKEMP, pour ma tâche actuelle, j'ai besoin d'une copie peu profonde (copier simplement des valeurs non-références).