Avatar billede dansermeddhtml Nybegynder
04. marts 2008 - 16:44 Der er 4 kommentarer

Ens men ikke identiske klasser

Jeg ved ikke om dette kan lade sig gøre, men here goes:

Jeg har et antal klasser der har et identisk, men ikke specificeret interface, altså.

Class1
{
public string text;
}
Class2
{
public string text;
}
Class3
{
public string text;
}

Det ovenstående er blot for at vise ideen; der er mange flere klasser, og de indeholder alle de samme +30 felter.
Sagen er så at disse klasser er fremmede for min applikation (og jeg kan ikke røre dem på nogen måde) - og jeg skal kunne pakke disse objekter ud og skabe instanser af min egen "pæne" type baseret herpå; men helst uden at lave en parsing metode for hver enkelt af dem. Og uden reflection, det skal ske runtime (og ofte) og operationen er derfor performancekritisk..

Jeg mener at have læst noget engang om at det rent faktisk er muligt at betragte en klasse som om den implementerer et interface den ikke gør - any clues?
Avatar billede nielle Nybegynder
04. marts 2008 - 17:18 #1
Ja, det er det også - det kaldes for et Adapter Pattern:

http://en.wikipedia.org/wiki/Adapter_pattern

Men det er ikke noget som spare dig så meget som en linje kode i forhold til at skrive en Parser for hver klasse.
Avatar billede arne_v Ekspert
05. marts 2008 - 04:09 #2
Jeg ved ikke om det hjælper dig på nogen måde, men følgen kode viser 2 forskellige
måder at gribe det an på:

using System;
using System.Reflection;

namespace E
{
    public class StupidOne
    {
        public string F1;
        public string F2;
        public StupidOne(string f1, string f2)
        {
            F1 = f1;
            F2 = f2;
        }
        public override string ToString()
        {
            return F1 + " " + F2;
        }
    }
    public class StupidTwo
    {
        public string F1;
        public string F2;
        public StupidTwo(string f1, string f2)
        {
            F1 = f1;
            F2 = f2;
        }
        public override string ToString()
        {
            return F1 + " " + F2;
        }
    }
    public class SmartContain
    {
        private string f1;
        private string f2;
        public SmartContain(string f1, string f2)
        {
            this.f1 = f1;
            this.f2 = f2;
        }
        public SmartContain(object o)
        {
            if(o is StupidOne)
            {
                StupidOne xo = (StupidOne)o;
                f1 = xo.F1;
                f2 = xo.F2;
            }
            else if(o is StupidTwo)
            {
                StupidTwo xo = (StupidTwo)o;
                f1 = xo.F1;
                f2 = xo.F2;
            }
            else
            {
                throw new ArgumentException("Not a supported type: " + o.GetType().FullName);
            }
        }
        public string F1
        {
            get
            {
                return f1;
            }
            set
            {
                f1 = value;
            }
        }
        public string F2
        {
            get
            {
                return f2;
            }
            set
            {
                f2 = value;
            }
        }
        public override string ToString()
        {
            return f1 + " " + f2;
        }
    }
    public class SmartLink
    {
        private object o;
        private FieldInfo f1;
        private FieldInfo f2;
        public SmartLink(object o)
        {
            this.o = o;
            try
            {
                f1 = o.GetType().GetField("F1", BindingFlags.Public | BindingFlags.Instance);
                f2 = o.GetType().GetField("F2", BindingFlags.Public | BindingFlags.Instance);
            }
            catch
            {
                throw new ArgumentException("Not a supported type: " + o.GetType().FullName);
            }
        }
        public string F1
        {
            get
            {
                return (string)f1.GetValue(o);
            }
            set
            {
                f1.SetValue(o, value);
            }
        }
        public string F2
        {
            get
            {
                return (string)f2.GetValue(o);
            }
            set
            {
                f2.SetValue(o, value);
            }
        }
        public override string ToString()
        {
            return F1 + " " + F2;
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            StupidOne o1 = new StupidOne("A", "B");
            StupidTwo o2 = new StupidTwo("C", "D");
            SmartContain xo1 = new SmartContain(o1);
            SmartContain xo2 = new SmartContain(o2);
            SmartLink zo1 = new SmartLink(o1);
            SmartLink zo2 = new SmartLink(o2);
            Console.WriteLine(o1);
            Console.WriteLine(o2);
            Console.WriteLine(xo1);
            Console.WriteLine(xo2);
            Console.WriteLine(zo1);
            Console.WriteLine(zo2);
            xo1.F2 = "X";
            xo2.F2 = "X";
            Console.WriteLine(o1);
            Console.WriteLine(o2);
            Console.WriteLine(xo1);
            Console.WriteLine(xo2);
            Console.WriteLine(zo1);
            Console.WriteLine(zo2);
            zo1.F2 = "Z";
            zo2.F2 = "Z";
            Console.WriteLine(o1);
            Console.WriteLine(o2);
            Console.WriteLine(xo1);
            Console.WriteLine(xo2);
            Console.WriteLine(zo1);
            Console.WriteLine(zo2);
            Console.ReadKey();
        }
    }
}
Avatar billede md_craig Nybegynder
06. marts 2008 - 15:52 #3
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Reflection;

namespace ForcedCast
{
    class Program
    {
        static void Main(string[] args)
        {
            object[] unknowns = new object[9];
            unknowns[0] = new A(1);
            unknowns[1] = new B(2);
            unknowns[2] = new C(3);
            unknowns[3] = new A(4);
            unknowns[4] = new B(5);
            unknowns[5] = new C(6);
            unknowns[6] = new A(7);
            unknowns[7] = new B(8);
            unknowns[8] = new C(9);

            HiPerfTimer timer = new HiPerfTimer();

            timer.Start();
            for (int i = 0; i < 10000; i++)
            {
                int value = 0;
                foreach(object o in unknowns)
                    value = (int)Microsoft.VisualBasic.Interaction.CallByName(o, "Value", Microsoft.VisualBasic.CallType.Get);
            }
            timer.Stop();
            Console.WriteLine(timer.Duration);

            timer.Start();
            for (int i = 0; i < 10000; i++)
            {
                int value = 0;
                foreach(object o in unknowns)
                    value = (int)o.GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance).GetValue(o,null);
            }
            timer.Stop();
            Console.WriteLine(timer.Duration);

            timer.Start();
            for (int i = 0; i < 10000; i++)
            {
                int value = 0;
                foreach (object o in unknowns)
                    value = new Unknown(o).Value;
            }
            timer.Stop();
            Console.WriteLine(timer.Duration);
        }
    }

   
    public class Unknown
    {
        private int a;
        public int Value
        {
            get { return a; }
        }
        public Unknown(int x)
        {
            a = x;
        }
        public Unknown(object o)
        {
            A oa = o as A;
            if (oa != null)
            {
                a = oa.Value;
                return;
            }

            B ob = o as B;
            if (ob != null)
            {
                a = ob.Value;
                return;
            }

            C oc = o as C;
            if (oc != null)
            {
                a = oc.Value;
                return;
            }
            throw new ArgumentException("Not a supported type: " + o.GetType().FullName);
        }
    }

    public class A
    {
        private int a;
        public int Value
        {
            get { return a; }
        }
        public A(int x)
        {
            a = x;
        }
    }

    public class B
    {
        private int a;
        public int Value
        {
            get { return a; }
        }
        public B(int x)
        {
            a = x;
        }
    }

    public class C
    {
        private int a;
        public int Value
        {
            get { return a; }
        }
        public C(int x)
        {
            a = x;
        }
    }

    internal class HiPerfTimer
    {
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency);

        private long startTime, stopTime;
        private long freq;

        // Constructor
        public HiPerfTimer()
        {
            startTime = stopTime = 0;
            if (QueryPerformanceFrequency(out freq) == false)
                throw new Win32Exception("Could not obtain Performance Frequency, high-performance counter is not supported!");
        }

        // Start the timer
        public void Start()
        {
            QueryPerformanceCounter(out startTime);
        }

        // Stop the timer
        public void Stop()
        {
            QueryPerformanceCounter(out stopTime);
        }

        // Returns the duration of the timer (in seconds)
        public double Duration
        {
            get
            {
                return (double)(stopTime - startTime) / (double)freq;
            }
        }
    }


Mja... hvis du virkelig gerne vil spare performance, kommer du jo nok ikke uden om den hårde vej. desvære...

Men om ikke andet er det med at få det lavet og så pakke det væk.

Overstående giver følgenden output (Fortolket):

Travasering af 10000 simple objecter alle med Propertyen "Value"
Visual Basic Interaction: 1,23202879621922 sec
.NET Reflection: 0,170679499476384 sec
Hardcoded Conversion: 0,00506896914690798 sec
Avatar billede nielle Nybegynder
13. marts 2008 - 08:29 #4
Hvad med noget respons?
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
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

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