Avatar billede lasserasch Juniormester
06. september 2015 - 02:03 Der er 7 kommentarer og
1 løsning

Automap mellem 2 interfaces

Hejsa.

Teoretisk spørgsmål. Jeg har en fungerende løsning, men vil høre om nogle kender til en smartere måde at gøre dette på.



1. Jeg bruger Unity som IoC Container i mit projekt.
2. Jeg bootstrapper implementeringerne af forskellige interfaces når applikationen starter. Så mit framework/Busniss logic projekt ved intet om konkrete implementeringer. Det opererer 100% via interfaces.

3. Mit issue er så at jeg har 2 forskellige interfaces.

Forsimplet eksempel kunne være :

Interface IProduct
string Title { get; set; }
string Text  { get; set; }
string Price { get; set; }


Interface IExtendedProduct
string Title { get; set; }
string Text  { get; set; }
string WithoutTaxPrice { get; set; }
string WitTaxPrice { get; set; }



Jeg har så en kontrol i min applikation, hvis datakilde kan tage en liste af IProduct.

Men jeg vil gerne føde kontrollen med en liste af IExtendedProduct som jeg har trukket ud af min database f.eks.

Igen, dette er kun et eksempel. Men jeg kender ikke den konkrete implementation af disse to interfaces. Det kunne være hvad som helst, og bestemmes uden for context af mit framework.

Derfor har jeg brug for at konvertere mine entities fra IExtendedProduct til Iproduct.

Det gør jeg idag via en helper metode. Mit spørgsmål er som om der ikke findes et ud af boksen framework eller noget andet som kan automappe mellem 2 interfaces i .net eller som 3. parts framework?

Til Sitecore, som jeg arbejder med meget, bruger jeg et framework kaldet GlassMapper. Det virker fint dertil og sparer en for meget arbejde. Så tænker at der vel næsten også må findes noget lign. til ren .net mapning mellem klasse eller interfaces?

Min nuværende helper metoder ser ud som herunder. Forestil jer så at der er 50 properties, hvor 40 af dem hedder det samme, mens kun 10 er forskellige. Det virker lidt tåbeligt at man manuelt skal sidde og mappe 40 felter, som en automapper sagtens kunne have gjort for en, (hvis sådan en altså findes).


public static List<IProduct> ConvertToIresultItemCollection(List<IExtendedProduct> sourceList)
        {
            var result = new List<IProduct>();

            foreach (var product in sourceList)
            {
                var resultItem = IoCHelper.Resolve<IProduct>();
                resultItem.Title = product.Title;
                resultItem.Text = product.Text;
                resultItem.Price = product.WithoutTaxPrice;
                result.Add(resultItem);
            }
            return result;
        }



Mvh.
Lasse
Avatar billede lasserasch Juniormester
06. september 2015 - 02:07 #1
Og det fandt jeg så vist lige noget om efterfølgende. Ved ikke om det er en løsning, men det skal der kigges nærmere på i morgen :-)


http://blog.goyello.com/2009/10/06/how-to-code-better-using-automapper/#!prettyPhoto
Avatar billede arne_v Ekspert
06. september 2015 - 02:09 #2
Altsaa du har en instans af:

List<IExtendedProduct>

of en metode:

public void Something(List<IProduct> data)

og du vil gerne kalde metode med din instans?

Sporgesmaal: er det ikke det som:

public void Something(List<out IProduct> data)

goer?
Avatar billede arne_v Ekspert
06. september 2015 - 02:47 #3
Hmm - proevede lige og det compiler ikke - out er ikke mulig ar bruge paa den maade - ihvertfakd ikke uden videre.
Avatar billede arne_v Ekspert
06. september 2015 - 03:18 #4
Men ideen ledte saa til en ny ide.

IReadOnlyList er out T.

Saa:

public static void Something(IReadOnlyList<IProduct> data)

(kraever dog .NET 4.5+)
Avatar billede arne_v Ekspert
06. september 2015 - 03:18 #5
Eksempel:


using System;
using System.Collections.Generic;

namespace E
{
    public interface IProduct
    {
        string Title { get; set; }
        string Text  { get; set; }
        decimal Price { get; set; }
    }
    public interface IExtendedProduct : IProduct
    {
        decimal WithTaxPrice { get; set; }
    }
    public class Product : IProduct
    {
        public string Title { get; set; }
        public string Text  { get; set; }
        public decimal Price { get; set; }
    }
    public class ExtendedProduct : Product, IExtendedProduct
    {
        public decimal WithTaxPrice { get; set; }
    }
    public class Program
    {
        public static void Something(IReadOnlyList<IProduct> data)
        {
            foreach(IProduct p in data)
            {
                Console.WriteLine(p.Title);
            }
        }
        public static void Main(string[] args)
        {
            List<IExtendedProduct> data = new List<IExtendedProduct>();
            data.Add(new ExtendedProduct { Title = "T1", Text = "Bla bla 1", Price = 10.00m, WithTaxPrice = 12.50m });
            data.Add(new ExtendedProduct { Title = "T2", Text = "Bla bla 2", Price = 20.00m, WithTaxPrice = 25.00m });
            Something(data);
            Console.ReadKey();
        }
    }
}
Avatar billede lasserasch Juniormester
06. september 2015 - 22:20 #6
Se det var jo godt nok smart. Virker perfekt og var lige hvad jeg har brug for.

Det eneste er at man så kun kan tilgå base klasse properties, men det er også okay til det jeg har brug for.

Det er små lækre sager de har tilføjet i .net 4.5.

Tak for tippet Arne.

Smid et svar for points.

Mvh.
Lasse
Avatar billede arne_v Ekspert
07. september 2015 - 00:44 #7
svar
Avatar billede arne_v Ekspert
07. september 2015 - 01:39 #8
Og bare for en god ordens skyld:
- muligheden for <out T> kom i .NET 4.0
- men det var 4.5 som tilfoejede IReadOnlyList<out T>
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester