11
votes

Copier les propriétés d'objet: réflexion ou sérialisation - ce qui est plus rapide?

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:

  1. Utilisez la réflexion, naviguez sur les propriétés du premier objet et copiez les valeurs. P> li>

  2. 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 Personne P1 code> à Personne P2 code>. p>

    pour cet échantillon simple - quelle méthode est plus rapide? p>

    Mise à jour forte> 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>

    foreach (PropertyInfo sourcePropertyInfo in copyFromObject.GetType().GetProperties())  
    {
        PropertyInfo destPropertyInfo = copyToObject.GetType().GetProperty(sourcePropertyInfo.Name);
    
        destPropertyInfo.SetValue(
            copyToObject,
            sourcePropertyInfo.GetValue(copyFromObject, null),
            null);
    }
    


6 commentaires

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).


5 Réponses :


0
votes

La sérialisation binaire est très rapide, je l'utilise beaucoup pour ce type de problème

Objets de clonage profond


2 commentaires

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 (le sérialisateur sous ObjectCopier ) obtient ses données? Astuce: il commence par "R" et sonne comme "déviation".



0
votes

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.


4 commentaires

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.



12
votes

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 d'entre eux pourraient être en train d'utiliser la réflexion comme mécanisme sous-jacent des objets de construction.

Edit # 1: Autant que je sache, BinaryFormatter 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?

EDIT # 2: SUR LA CURIOSITÉ, j'ai Exécuter un test simple. BinaryFormatter VS Réflexion en termes d'exécution Copie peu profonde . Le code de réflexion que j'ai utilisé peut être vu ici: xxx

Quels sont les résultats par rapport à ObjectCopier Classe que vous utilisez? La réflexion semble exécuter 7 fois plus rapide que le code de sérialisation. Cela s'applique toutefois à la classe de la personne avec champs publics . Pour les propriétés, la différence est toujours visible, mais elle n'est que 2 fois plus rapide.

Je suppose que la différence provient du fait que BinaryFormatter 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.

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: -)


sidenote
Comme avec tous les "je me demandais ..." 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.


3 commentaires

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.



8
votes

En fin de compte, des sérialiseurs à usage général (tels que Binarinformatter , via ObjectCopier ) utilise la réflexion . Comment bien 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é.

Puisque vous ne voulez que une copie peu profonde, un outil tel que FOWORAPPER est l'outil le plus approprié 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 getvalue () / SETValue () ), mais ça ne " t avoir les coûts de sérialisation.

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 binarinformatter moi-même, mais je suis très difficile à propos de la sérialisation; p

Ce serait bien sûr trivial à droite de la réflexion de base qui fait la même chose via getvalue () etc., mais ce serait lent. Une autre option intéressante ici est que vous pouvez utiliser l'API EXPRESSE 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>


0 commentaires

0
votes
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));
        }
    }
}

1 commentaires

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.