myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Gemeinschaft » .NET-Komponenten und C#-Snippets » Typkonvertierungen mit TypeConverter (Extension)
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Typkonvertierungen mit TypeConverter (Extension)

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
dr4g0n76
myCSharp.de-Poweruser/ Experte

avatar-1768.jpg


Dabei seit: 07.07.2005
Beiträge: 2.879
Entwicklungsumgebung: SharpDevelop/VS.NET
Herkunft: Deutschland


dr4g0n76 ist offline

Typkonvertierungen mit TypeConverter (Extension)

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Mit untenstehender Klasse ist folgendes möglich:
(1. Version)

Arrays, Listen bzw. IEnumerables können konvertiert werden.
Von einem Typ in den anderen.
Selbst wenn die Klasse keinen entsprechenden AddRange-Befehl oder Konstruktor hat, ist das auch möglich.

Ich muss also nicht mehr schreiben:



Wenn z.B.

C#-Code:
    //Complex conversions
            char[] a = new char[] { 'm', 'u', 'l', 't', 'u', 'm', 'e', 's', 'c' };
            byte[] b = new byte[] { 65, 66, 66, 65, 65, 66, 65, 66 };

            int[] resultIntArrayFromCharArray = (int[])typeof(int[]).Cast(a);
            int[] resultIntArrayFromByteArray = (int[])typeof(int[]).Cast(b);
            char[] resultCharArray = (char[])typeof(char[]).Cast(b);
            byte[] resultByteArray = (byte[])typeof(byte[]).Cast(a);
            //--------------------------------------------------------------------------
            //Convert from IEnumerable<Guid> to ObservableCollection<Guid>
            IEnumerable<Guid> guids = new Guid[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
            ObservableCollection<Guid> observableCollectionGuid = (ObservableCollection<Guid>)typeof(ObservableCollection<Guid>).Cast(guids);

            //Convert from ObservableCollection<Guid> to IEnumerable<Guid>
            ObservableCollection<Guid> observableCollectionGuid2 = new ObservableCollection<Guid>(new Guid[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() });
            IEnumerable<Guid> guids2 = (IEnumerable<Guid>)typeof(IEnumerable<Guid>).Cast(observableCollectionGuid2);

            //--------------------------------------------------------------------------
            //Simple conversion
            int intValue = 339;
            double? doubleValueCastedNullable = (double?)typeof(double?).Cast(intValue);

            intValue = 90943;
            double doubleValueCasted = (double)typeof(double).Cast(intValue);

            double doubleValue = 7.0d;
            float floatValueCasted = (float)typeof(float).Cast(doubleValue);

            float floatValue = 3.09f;
            decimal decimalValueCasted = (decimal)typeof(decimal).Cast(floatValue);

            //--------------------------------------------------------------------------
            try
            {
                //at the moment an invalid cast exception is expected, when casting an array to one element
                string[] textValues = new string[] { "Hallo", "Hello", "Hola", "olá", "buna", "jak", "dag" };
                string sText = (string)typeof(string).Cast(textValues);
            }
            catch (InvalidCastException ex)
            {
                //so now we get an invalid cast
            }
            catch (Exception ex)
            {
            }

            //This will be casted, but at the moment makes no sense at all.
            //So one shouldn't do this.
            try
            {
                byte[] intValues = new byte[] { 7, 3, 9, 8, 5, 9 };
                int value = (int)typeof(int).Cast(intValue);
            }
            catch (InvalidCastException ex)
            {
            }
            catch (Exception ex)
            {
            }

            //--------------------------------------------------------------------------
            //This is possible: cast a single value to a list
            string textValue = "Hallo";
            List<string> sText2 = (List<string>)typeof(List<string>).Cast(textValue);

            //This is possible: cast a single value to a list
            Guid singleGuid = Guid.NewGuid();
            List<Guid> guidsOfSingleGuid = (List<Guid>)typeof(List<Guid>).Cast(singleGuid);

            intValue = 737;
            List<int> intsOfSingleInt = (List<int>)typeof(List<int>).Cast(intValue);

            bool trueValue = true;
            List<bool> boolsOfSingleBool = (List<bool>)typeof(List<bool>).Cast(trueValue);


            //--------------------------------------------------------------------------
            //This is also possible: Convert object to string: internally call object.ToString()
            intValue = 3457;
            string intValueCastedToString = (string)typeof(string).Cast(intValue);

C#-Code:
using System;
using System.Runtime.CompilerServices;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using DynamicFramework.Iterators;

namespace DynamicFramework.TypeCast
{
    /// <summary>
    /// Use this class to do any type casts that would consume programming and code in one line.
    /// even casting like this is allowed:
    ///
    ///
    ///
    /// </summary>
    public static class TypeCast
    {
        // This is the method exposing the rest of the functionality
        /// <summary>
        /// Casts the specified type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="obj">The object.</param>
        /// <returns></returns>
        public static object Cast(this Type type, object obj)
        {
            return GetConverter(type, obj)(obj);
        }

        /// <summary>
        /// Converters contains the cached converters,
        /// so using once it might be slow, the second time a cached converter
        /// will be used if possible.
        /// </summary>
        private static readonly IDictionary<PairOfTypes, Func<object, object>> converters =
            new Dictionary<PairOfTypes, Func<object, object>>();

        private static readonly ParameterExpression convParameter =
            Expression.Parameter(typeof(object), "val");

        /// <summary>
        /// Gets the converter.
        /// </summary>
        /// <param name="targetType">Type of the target.</param>
        /// <param name="val">The value.</param>
        /// <returns></returns>
        /// This is the method with the "guts" of the implementation
        [MethodImpl(MethodImplOptions.Synchronized)]
        private static Func<object, object> GetConverter(Type targetType, object val)
        {
            var fromType = val != null ? val.GetType() : typeof(object);
            var key = new PairOfTypes(fromType, targetType);
            Func<object, object> res;
            if (converters.TryGetValue(key, out res))
            {
                return res;
            }

            bool bConverted = true;
            try
            {
                res = (Func<object, object>)Expression.Lambda(
                    Expression.Convert(
                        Expression.Convert(
                            Expression.Convert(
                                convParameter
                            , fromType
                            )
                        , targetType
                        )
                    , typeof(object)
                    )
                , convParameter
                ).Compile();
                converters.Add(key, res);
            }
            catch (InvalidOperationException ex)
            {
                bConverted = false;
            }
            catch (Exception ex)
            {
                bConverted = false;
            }
            if (!bConverted)
            {
                IList listTargetType = null;
                IEnumerable listSourceType = val as IEnumerable;
                if (listSourceType != null)
                {
                    if (targetType.IsArray)
                    {

//TODO: for silverlight, what to do if there is an interface...
#if !SILVERLIGHT
                        if (listSourceType.GetType().GetInterface(typeof(IList).Name) != null)
                        {
                            IList list = (IList)listSourceType;
                            int count = list.Count;
                            listTargetType = (IList)Activator.CreateInstance(targetType, count);

                            int i = 0;
                            foreach (object oElement in Iter.All(listSourceType))
                            {
                                //unbox if needed, don't know yet, how to do by reflection
                                if (oElement.GetType() == typeof(char) && GetBaseTypeOfGenericIEnumerableType(listTargetType.GetType()) == typeof(byte))
                                {
                                    listTargetType[i++] = (byte)(char)oElement;
                                }
                                else
                                {
                                    listTargetType[i++] = oElement;
                                }
                            }
                        }
#endif
                    }
                    else
                    {
                        if (targetType == typeof(string))
                        {
                            throw new InvalidCastException(); //this is invalid, because one doesn't know how to convert an array into one element here.
                        }
                        listTargetType = (IList)Activator.CreateInstance(targetType);

                        if (val.GetType() == typeof(string))
                        {
                            listTargetType.Add(val);
                        }
                        else
                        {
                            foreach (object oElement in listSourceType)
                            {
                                listTargetType.Add(oElement);
                            }
                        }
                    }
                    //still null? consider case converting ONE element on source into list of elements in target
                }
                else
                {
                    if (targetType.FullName.Contains(val.GetType().FullName))
                    {
                        Type baseType = GetBaseTypeOfGenericIEnumerableType(targetType);
                        listTargetType = (IList)Activator.CreateInstance(targetType);
                        listTargetType.Add(val);
                    }
                }
                if (targetType == typeof(string) && listTargetType == null)
                {
                    res = (Func<object, object>)(x => val.ToString());
                    converters.Add(key, res);
                    return res;
                }
                else if (targetType.IsGenericType
                    && listTargetType == null
                    && targetType.Name.Contains("List`1"))
                {
                    listTargetType = (IList)Activator.CreateInstance(targetType);
                    listTargetType.Add(val);
                }
                res = (Func<object, object>)(x => listTargetType); //this will get us what we want
                //converters.Add(key, res);
            }
            return res;
        }

        //TODO: avoid this method, if possible, but for the moment it's perfect.
        /// <summary>
        /// Found no other way to do this yet.
        /// </summary>
        /// <param name="targetType"></param>
        /// <returns></returns>
        public static Type GetBaseTypeOfGenericIEnumerableType(Type targetType)
        {
            string[] elements = System.Text.RegularExpressions.Regex.Split(targetType.FullName, @",|\[\[");
            if (elements.Length > 1)
            {
                return Type.GetType(elements[1]);
            }
            else
            {
                return Type.GetType(elements[0].TrimEnd(']').TrimEnd('['));
            }
        }
#if !FRAMEWORK35
        /// <summary>
        /// Converts the specified original.
        /// </summary>
        /// <param name="original">The original.</param>
        /// <returns></returns>
        public static ObservableCollection<object> Convert(IEnumerable original)
        {
            return new ObservableCollection<object>(original.Cast<object>());
        }

        /// <summary>
        /// Converts the specified original.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="original">The original.</param>
        /// <returns></returns>
        public static ObservableCollection<T> Convert<T>(IEnumerable<T> original)
        {
            return new ObservableCollection<T>(original);
        }

        /// <summary>
        /// Converts the specified original.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="original">The original.</param>
        /// <returns></returns>
        public static ObservableCollection<T> Convert<T>(IEnumerable original)
        {
            return new ObservableCollection<T>(original.Cast<T>());
        }
#endif

        /// <summary>
        /// Find out how to really unbox!!!
        /// </summary>
        /// <param name="oElement"></param>
        /// <param name="sourceType"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        private static object Unbox(object oElement, Type sourceType, Type destinationType)
        {
            if (sourceType == typeof(char) && destinationType == typeof(byte))
            {
                oElement = (byte)(char)oElement;
            }
            return oElement;
        }

        // This class provides Equals and GetHashCode
        // for a pair of System.Type objects.
        private class PairOfTypes
        {
            private readonly Type first;
            private readonly Type second;
            public PairOfTypes(Type first, Type second)
            {
                this.first = first;
                this.second = second;
            }
            public override int GetHashCode()
            {
                return 31 * first.GetHashCode() + second.GetHashCode();
            }
            public override bool Equals(object obj)
            {
                if (obj == this)
                {
                    return true;
                }
                var other = obj as PairOfTypes;
                if (other == null)
                {
                    return false;
                }
                return first.Equals(other.first)
                    && second.Equals(other.second);
            }
        }
    }
}


Dateianhang:
unknown TypeCastTest.zip (107,03 KB, 178 mal heruntergeladen)

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von dr4g0n76 am 21.01.2015 14:21.

20.11.2013 19:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr.
dr4g0n76
myCSharp.de-Poweruser/ Experte

avatar-1768.jpg


Dabei seit: 07.07.2005
Beiträge: 2.879
Entwicklungsumgebung: SharpDevelop/VS.NET
Herkunft: Deutschland

Themenstarter Thema begonnen von dr4g0n76

dr4g0n76 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Anmerkung:

Gerade erst bemerkt.
Die Klasse benutzt einen Namespace der sich DynamicFramework.Iterators nennt.

Das ist nichts anderes als die komplett unveränderte Lösung für Iteratoren von Herbivore auf:

 Hilfreiche Iteratoren / Improving Foreach

EDIT: Damit lässt sich die Klasse benutzen und fehlerfrei kompilieren.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dr4g0n76 am 14.01.2015 14:12.

14.01.2015 14:12 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
dr4g0n76
myCSharp.de-Poweruser/ Experte

avatar-1768.jpg


Dabei seit: 07.07.2005
Beiträge: 2.879
Entwicklungsumgebung: SharpDevelop/VS.NET
Herkunft: Deutschland

Themenstarter Thema begonnen von dr4g0n76

dr4g0n76 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich habe ein Beispiel-Projekt angehängt im obersten Post, dann kann jeder ausprobieren und muss nicht erst beide Klassen in ein Projekt kopieren.

Auf jede der Funktionen die über die entsprechenden Buttons der Form gesetzt sind, sind Breakpoints gesetzt, so dass sich jeder in Ruhe anschauen kann was passiert.

Ich editiere den oberen Beitrag nochmals, so dass einige Dinge etwas klarer werden sollten.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dr4g0n76 am 21.01.2015 14:24.

21.01.2015 14:23 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 2 Jahre.
dr4g0n76
myCSharp.de-Poweruser/ Experte

avatar-1768.jpg


Dabei seit: 07.07.2005
Beiträge: 2.879
Entwicklungsumgebung: SharpDevelop/VS.NET
Herkunft: Deutschland

Themenstarter Thema begonnen von dr4g0n76

dr4g0n76 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hat irgendjemand zufällig eine Idee, wie man bei

C#-Code:
List<Guid> guidsOfSingleGuid = (List<Guid>)typeof(List<Guid>).Cast(singleGuid);

um das

C#-Code:
(List<Guid>)typeof(List<Guid>).Cast(singleGuid);

herumkommt?

Also dass man statt (List<Guid>)typeof(List<Guid>).Cast(singleGuid);
quasi was ganz kurzes schreiben könnte, was eben näher an:

C#-Code:
List<Guid> guidsOfSingleGuid = singleGuid.CastTo(List<Guid>);

ist?
09.03.2017 18:38 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.161
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi dr4g0n76,

meinst du soetwas:

C#-Code:
public static IEnumerable<T> ToEnumerable<T>(this T item)
{
  yield return item;
}

C#-Code:
List<Guid> guidsOfSingleGuid = singleGuid.ToEnumerable().ToList();
09.03.2017 18:54 Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.283
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo dr4g0n76,

wenn dann wohl

C#-Code:
List<Guid> guidsOfSingleGuid = singleGuid.CastTo<List<Guid>>();

denn sonst müßtest du ja

C#-Code:
List<Guid> guidsOfSingleGuid = singleGuid.CastTo(typeof(List<Guid>));

schreiben.

Und das geht dann per

C#-Code:
public static T CastTo(this Guid guid)
{
    return (T)typeof(T).Cast(guid);
}

Wenn T aber immer List<Guid> ist, kannst du es natürlich vereinfachen (spezialisieren):

C#-Code:
public static List<Guid> CastTo(this Guid guid)
{
    return (List<Guid>)typeof(List<Guid>).Cast(guid);
}

(Extension-Methoden müssen dann natürlich in eine eigene statische Klasse z.B. GuidExtensions)

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am 09.03.2017 20:16.

09.03.2017 20:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 5 Jahre.
Der letzte Beitrag ist älter als 2 Jahre.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 22.07.2019 22:37