Domanda

Ho scritto una classe con un singolo metodo statico che copia i valori delle proprietà da un oggetto a un altro. Non importa che tipo sia ogni oggetto, solo che hanno proprietà identiche. Fa quello che mi serve, quindi non lo sto progettando ulteriormente, ma quali miglioramenti faresti?

Ecco il codice:

public class ShallowCopy
{
    public static void Copy<From, To>(From from, To to)
        where To : class
        where From : class
    {
        Type toType = to.GetType();
        foreach (var propertyInfo in from.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance))
        {
            toType.GetProperty(propertyInfo.Name).SetValue(to, propertyInfo.GetValue(from, null), null);
        }
    }
}

Lo sto usando come segue:

EmployeeDTO dto = GetEmployeeDTO();
Employee employee = new Employee();
ShallowCopy.Copy(dto, employee);
È stato utile?

Soluzione

I tuoi DTO sono serializzabili? Me lo aspetterei, nel qual caso:

MemberInfo[] sm = FormatterServices.GetSerializableMembers(typeof(From));
object[] data = FormatterServices.GetObjectData(from, sm);
FormatterServices.PopulateObjectMembers(to, sm, data);

Ma nota che non sono davvero d'accordo con questo approccio generale. Preferirei un contratto forte per la copia dei tuoi DTO implementati da ogni DTO.

Altri suggerimenti

  • Modifica i nomi dei parametri del tipo in modo che siano conformi alle convenzioni di denominazione, ad es. TFrom e TTo, o TSource e TDest (o TDestination).

  • Esegui la maggior parte del tuo lavoro in un tipo generico anziché solo in un metodo generico. Ciò consente di memorizzare nella cache le proprietà, oltre a consentire l'inferenza del tipo. L'inferenza del tipo è importante nella sezione "TFrom" parametro, in quanto consentirà l'utilizzo di tipi anonimi.

  • Potresti potenzialmente accelerarlo in modo accecante generando dinamicamente codice per eseguire la copia della proprietà e conservarlo in un delegato valido per " da " genere. O potenzialmente generarlo per ogni coppia da / a, il che significherebbe che la copia effettiva non dovrebbe assolutamente usare la riflessione! (Preparare il codice sarebbe un hit una tantum per coppia di tipi, ma si spera che tu non abbia troppe coppie.)

Un nuovo metodo che ha creato una nuova istanza di To e chiamato il metodo Copy () prima di tornare potrebbe essere utile.

In questo modo:

public static To Create<From, To>(From from)
    where To : class, new()
    where From : class
{
    var to = new To();
    Copy(from, to);
    return to;
}

Decidi cosa vuoi fare se vengono passati oggetti di tipi che condividono alcune proprietà ma non tutte. Verificare l'esistenza della proprietà nell'oggetto From nell'oggetto To prima di provare a impostarne il valore. Fai la "cosa giusta" quando vieni in una proprietà che non esiste. Se tutte le proprietà pubbliche devono essere identiche, dovrai verificare se sono state impostate tutte sull'oggetto To e gestire il caso in cui non lo hai fatto in modo appropriato.

Suggerirei anche che potresti voler usare gli attributi per decorare le proprietà che devono essere copiate e ignorarne altre. Ciò ti consentirebbe di andare avanti e indietro tra i due diversi oggetti più facilmente e di continuare a mantenere alcune proprietà pubbliche derivate anziché archiviate nel tuo oggetto aziendale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top