Semplice Convenzione Automapper per Mapping a due vie (Enti da / per ViewModels)
-
21-09-2019 - |
Domanda
UPDATE: questa roba è evoluto in un bel progetto, vede a http: // valueinjecter.codeplex.com
check this out, ho appena scritto un semplice automapper, prende il valore dalla proprietà con lo stesso nome e il tipo di un oggetto e la mette in un altro, ed è possibile aggiungere eccezioni (IFS, switch) per ogni tipo potrebbe essere necessario < br>
quindi dimmi cosa ne pensi a riguardo?
L'ho fatto così ho potuto fare qualcosa di simile:
Product –> ProductDTO
ProductDTO –> Product
è così che iniziata:
utilizzare il tipo di "oggetto" nei miei Ingressi / Dto / ViewModels per DropDowns perché io mando il codice html di un IEnumerable
public void Map(object a, object b)
{
var pp = a.GetType().GetProperties();
foreach (var pa in pp)
{
var value = pa.GetValue(a, null);
// property with the same name in b
var pb = b.GetType().GetProperty(pa.Name);
if (pb == null)
{
//no such property in b
continue;
}
if (pa.PropertyType == pb.PropertyType)
{
pb.SetValue(b, value, null);
}
}
}
UPDATE:
il vero utilizzo:
i metodi di build (ingresso = Dto):
public static TI BuildInput<TI, T>(this T entity) where TI: class, new()
{
var input = new TI();
input = Map(entity, input) as TI;
return input;
}
public static T BuildEntity<T, TI, TR>(this TI input)
where T : class, new()
where TR : IBaseAdvanceService<T>
{
var id = (long)input.GetType().GetProperty("Id").GetValue(input, null);
var entity = LocatorConfigurator.Resolve<TR>().Get(id) ?? new T();
entity = Map(input, entity) as T;
return entity;
}
public static TI RebuildInput<T, TI, TR>(this TI input)
where T: class, new()
where TR : IBaseAdvanceService<T>
where TI : class, new()
{
return input.BuildEntity<T, TI, TR>().BuildInput<TI, T>();
}
nel controller:
public ActionResult Create()
{
return View(new Organisation().BuildInput<OrganisationInput, Organisation>());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(OrganisationInput o)
{
if (!ModelState.IsValid)
{
return View(o.RebuildInput<Organisation,OrganisationInput, IOrganisationService>());
}
organisationService.SaveOrUpdate(o.BuildEntity<Organisation, OrganisationInput, IOrganisationService>());
return RedirectToAction("Index");
}
Il metodo vera mappa
public static object Map(object a, object b)
{
var lookups = GetLookups();
var propertyInfos = a.GetType().GetProperties();
foreach (var pa in propertyInfos)
{
var value = pa.GetValue(a, null);
// property with the same name in b
var pb = b.GetType().GetProperty(pa.Name);
if (pb == null)
{
continue;
}
if (pa.PropertyType == pb.PropertyType)
{
pb.SetValue(b, value, null);
}
else if (lookups.Contains(pa.Name) && pa.PropertyType == typeof(LookupItem))
{
pb.SetValue(b, (pa.GetValue(a, null) as LookupItem).GetSelectList(pa.Name), null);
}
else if (lookups.Contains(pa.Name) && pa.PropertyType == typeof(object))
{
pb.SetValue(b, pa.GetValue(a, null).ReadSelectItemValue(), null);
}
else if (pa.PropertyType == typeof(long) && pb.PropertyType == typeof(Organisation))
{
pb.SetValue(b, pa.GetValue<long>(a).ReadOrganisationId(), null);
}
else if (pa.PropertyType == typeof(Organisation) && pb.PropertyType == typeof(long))
{
pb.SetValue(b, pa.GetValue<Organisation>(a).Id, null);
}
}
return b;
}
Soluzione
Una cosa che si potrebbe desiderare di aggiungere è quello di memorizzare nella cache i bit di riflessione. Se si associa un oggetto due volte, probabilmente non si desidera cercare tutte le cose riflessione di nuovo. Inoltre, le cose come GetValue e SetValue sono piuttosto lento, sono passato ai delegati tardiva + Reflection.Emit per accelerare le cose.
Altri suggerimenti
Basta usare automapper . Questo va bene, ma sarà crescere in un mini progetto.
solo alcune cose AM (quello vero) fa è:
- segnalazione se si dispone di proprietà che non può essere mappato
- appiattimento oggetti
- fornendo ganci di personalizzare alcuni aspetti, non in una grande dichiarazione interruttore
- utilizzando Expression.Compile per motivi di Potenza, piuttosto che di riflessione direttamente
Ma è certamente uno spazio interessante per pasticciare in, e l'idea di mappatura automatica è sicuramente utile.
Un po 'come in DI 15 o noreferrer 33 linee vs Ninject o dai suoi amici -?. fresco, ma perché
Io lo prendo che hai letto il articolo e commenti riguardo la mappatura 2 modo su Jimmy blog ?
Solo un pensiero:
Ci si potrebbe chiedere quale sia il punto di un'astrazione è se l'astrazione è così facilmente mappato a quello che è astratto.
è possibile aggiungere eccezioni (IFS, switch) per ogni tipo potrebbe essere necessario
Non hai intenzione di fare questo. Sul serio. istruzioni case che agiscono per tipi di oggetti sono cattivo stile OOP. Voglio dire, davvero male. Come guidare con un drink di vodka all'interno del vostro stomaco. Si può lavorare per qualche tempo, ma alla fine si ottiene nei guai.
OK Jimmy ti ha detto di non usare automapper ... ma scommetto che voleva dire qualcos'altro. Ora, avete inventato qualcosa di diverso - qualcosa che rendono Jimmy felice? ;-) No, hai appena fatto il proprio mezzo laminati automapper. E Jimmy ti ha detto di non usarlo! ; -)
Quindi, ecco il mio suggerimento: ignorare quello che dice Jimmy, basti pensare se stessi .. e utilizzare automapper; -)