Cercando di creare una convenzione di mappatura per oggetti C #

4

quindi questo è C # ma potrebbe essere applicato a qualsiasi linguaggio OO in cui esistono diversi insiemi di oggetti tra diversi livelli di un'applicazione.

Abbiamo cercato di creare una convenzione all'interno del team per dove mettere il codice quando si mappano oggetti in un livello in oggetti in un altro livello. Per esempio; mappatura di un oggetto di trasferimento dati su un oggetto di servizio utilizzato da un servizio WCF o qualcosa di simile. Ho i seguenti metodi che ho visto essere usato e sto cercando di decidere quale sarebbe preferito da qualcuno che guarda il codice, e quale di questi si adatta meglio con gli idiomi C # naturali.

Questi esempi usano AutoMapper per mappare un oggetto Foo a un oggetto Bar , ma si applica a qualsiasi framework di mappatura, o semplicemente creando manualmente Bar da Foo con un inizializzatore di oggetti . Entrambi questi oggetti rappresentano gli stessi dati, ma si trovano in diversi gruppi:

1) Costruttore su Bar

public class Bar
{
    public Bar(Foo foo)
    {
        Mapper.Map(foo, this);
    }
}

2) Metodo di fabbrica su Barra

public class Bar
{
    public static Bar CreateFrom(Foo foo)
    {
        return Mapper.Map<Bar>(foo);
    }
}

3) Metodo su Foo per ritornare Bar

public class Foo
{
    public Bar GetBar()
    {
        return Mapper.Map<Bar>(this);
    }
}

4) Operatore di conversione del tipo esplicito su Foo in modo che possa essere convertito in Bar

public class Foo
{
    public static explicit operator Bar(Foo foo)
    {
        return Mapper.Map<Bar>(foo);
    }
}

5) Alcune implementazioni del modello di fabbrica

public class BarFactory : IFactory<Bar>
{
    public Bar Create(Foo foo)
    {
        return Mapper.Map<Bar>(foo);
    }
}

6) Basta farlo nel codice pezzo che ti serve in

    public void SomeMethod()
    {
        Foo foo = fooRepository.GetFoo();

        //I need it to be bar now...
        Bar bar = Mapper.Map<Bar>(foo);

    }

Dichiarazione di non responsabilità: vorrei non aver usato AutoMapper in questo esempio. Immagina "AutoMapper" qui "IMappingProvider" o "IObjectConverter" o qualcosa

    
posta jcharlesworthuk 10.07.2014 - 12:39
fonte

3 risposte

4

In tutti i casi, preferirei # 5. Nell'esempio 1-2-3-4 di codice, penso che l'oggetto dominio non debba conoscere gli oggetti DTO relativi a lui.

Diciamo che hai

public class User
{
    ... some properties ...
} 

public class UserThumbnail
{
    ... some properties ...
} 

Un oggetto Modello dominio (Utente) non deve sapere che un oggetto DTO (UserThumbnail) sta utilizzando le proprietà dell'utente, perché aggiunge l'accoppiamento tra queste classi e la responsabilità della creazione dell'oggetto DTO (UserThumbnail) viene aggiunta a Oggetto dominio (utente).

Quindi, se i casi d'uso della tua azienda non specificano che un utente dovrebbe essere in grado di creare una UserThumbnail, allora penso che non dovresti farlo. Ecco perché classi come Factory dovrebbero essere utilizzate in questo caso: perché gli oggetti DTO non inquinano gli oggetti di dominio. Se in questo caso viene utilizzata una factory, l'oggetto dominio non sa nemmeno che l'oggetto DTO esiste.

Per il # 6, se cambi mai AutoMapper in un altro strumento di mappatura, dovresti cercare nel tuo codice. Se hai usato una fabbrica, sai che tutte le chiamate AutoMapper ci sono.

Mapper.Map sta facendo 2 cose: crea istanze e mappa le proprietà. Factory Pattern è la soluzione se vuoi isolare il codice di creazione dell'oggetto.

    
risposta data 10.07.2014 - 14:26
fonte
1

Normalmente preferirei # 3 - GetBar è molto ovvio da dove viene e cosa ottieni, ma in questo caso, mappando le classi, utilizzerei spesso l'operatore di conversione.

Ma la mappatura non sembra che tu stia lanciando, stai davvero creando qualcosa di nuovo che non è contenuto nell'oggetto (dove utilizzerei GetBar), ma semplicemente convertendolo (barra dell'operatore).

Quindi in questo caso, userei CreateFrom - è ovvio che stai facendo un nuovo oggetto mappato per rappresentare qualcos'altro che è relativo a Foo e non a Foo o a un sottoinsieme contenuto o ereditato di Foo in qualsiasi forma o modulo.

    
risposta data 10.07.2014 - 13:04
fonte
1

Vorrei scrivere una classe mapper e mappare manualmente i dati da un tipo all'altro. Sì, è una buona idea, ma tu hai tutto sotto controllo, è semplice e fa il lavoro. Lo terrei fuori dall'assemblaggio del modello poiché gli oggetti del modello non dovrebbero avere alcuna conoscenza dei tipi restituiti da WCF.

public class FooMapper
{
    public Foo Map(Bar bar)
    {
        return new Foo
            {
                ValueOne = bar.ValueOne,
                ValueTwo = bar.ValueTwo,
                ....
            };
    }
}
    
risposta data 13.07.2014 - 20:22
fonte

Leggi altre domande sui tag