Genel tip dönüşüm FROM dizesi


234

Başka bir sınıf için "özellikleri" depolamak için kullanmak istediğiniz bir sınıf var. Bu özelliklerin bir adı ve değeri vardır. İdeal olarak, ne istiyorum eklemek mümkün olmaktır daktilo döndü "değer" Ben olmak istiyorum hep tiptedir böylece, özellikleri.

Tip her zaman ilkel olmalıdır. Bu sınıf, adı ve değeri temel olarak dize olarak saklayan soyut bir sınıfın alt sınıfını oluşturur. Bu alt sınıfın temel sınıfa bir tür güvenlik ekleyeceği (ve beni bazı dönüşümlerde koruyacağı) fikri.

Yani, (kabaca) bu bir sınıf yarattık:

public class TypedProperty<DataType> : Property
{
    public DataType TypedValue
    {
        get { // Having problems here! }
        set { base.Value = value.ToString();}
    }
}

Soru şu:

Dizeden bir ilkele dönüştürmenin "genel" bir yolu var mı?

( ITryParsable gibi bir şey ideal olurdu!) Yönetim Kurulu arasında dönüşüm bağlayan herhangi bir genel arayüzü bulamıyorum .


Ben sadece bir pasaj bile somut sınıfınıza bir örnek görmek istiyorum. :)
Jon Limjap

lütfen temel sınıfınızın ilgili bölümlerini yayınlayabilir misiniz?
JJS

Herkes burada cevapları alabilir miyim merak ediyorum. Net Standart 1.2: /
Dan Rayson

Yanıtlar:


374

Niyetlerini doğru anladığımdan emin değilim, ama bunun yardımcı olup olmadığını görelim.

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
        set { base.Value = value.ToString();}
    }
}

Birkaç gündür bir akışın genel bir türe nasıl serileştirileceğini merak ediyorum. Teşekkürler :)
Tuzak

3
Katılıyorum, Convert.ChangeTypeçok evrensel ve genişletilebilir bir çözüm olmamasına rağmen , çoğu temel tip için çalışıyor. daha iyi bir şey gerekiyorsa, bu yöntemi Tim'in önerdiği gibi daha büyük bir şeye sarmak veya tamamen farklı dönüşüm yöntemi kullanmak sorun değildir.
lubos hasko

18
Kesinlikle nereye eklemek istiyorsunuz T: IConvertible
MikeT

5
T tipi IConvertible değil, baz tipi olmalıdır.
chapluck

74

lubos hasko'nun yöntemi nullables için başarısız oluyor. Aşağıdaki yöntem nullables için işe yarayacaktır. Yine de gelmedim. Google üzerinden buldum: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx "Tuna Toksoz" a Kredi

İlk kullanım:

TConverter.ChangeType<T>(StringValue);  

Sınıf aşağıda.

public static class TConverter
{
    public static T ChangeType<T>(object value)
    {
        return (T)ChangeType(typeof(T), value);
    }

    public static object ChangeType(Type t, object value)
    {
        TypeConverter tc = TypeDescriptor.GetConverter(t);
        return tc.ConvertFrom(value);
    }

    public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
    {

        TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
    }
}

Enums ve Diğer Karmaşık yapılar için bir Fallback dönüştürme seçenekleri eklemek istiyorum, ama iyi çağrı.
Tomer W

2
Neden RegisterTypeConverter? Dönüştürücüleri önceden kaydetmemiz gerekiyor mu? (ne yazık ki bağlantı öldü, bu yüzden okuyamadım)
Cohen

Birden dönüşümler için muhtemelen oluşturmalısınız tc( TypeConvertersadece) bir kez. TypeConverteryavaştır çünkü TypeConverterAttribute. Tek bir özel TypeConverteralanı başlatırsanız , TypeConverterbirçok kez yeniden kullanabilmeniz gerekir .
Kevin P. Rice

İyi çalışıyor, ancak T bir ise object, bir istisna atar. `İf (typeof (T) .IsPrimitive) {return TConverter.ChangeType <T> (StringValue) kullanarak bunu çözebildim. } else {object o = (nesne) StringValue; geri vermek; } `Kullanım örneğinin yerine TConverter.ChangeType<T>(StringValue)
Matt

14

Birçok tür için (tamsayı, çift, DateTime vb.), Statik bir Ayrıştırma yöntemi vardır. Yansımayı kullanarak onu çağırabilirsiniz:

MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}

8
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptorGetConvertorbir Typenesneyi kabul eden yönteme sahip sınıftır ve daha sonra belirtilen nesne için ConvertFromdönüştürmek için yöntem çağırabilirsiniz value.


Şahsen bu arabirimin, tüm sınıfınızda IConvertible arabirimini uygulamanız gerektiğinden Convert.ChangeType yöntemi yerine dönüştürme işlemi için daha iyi olduğunu düşünüyorum.
Sauleil

3

Muhtemelen bir nitelik sınıfı gibi bir yapı kullanabilirsiniz . Bu şekilde, bir dizeyi kendi türünün değerine nasıl dönüştüreceğini bilen parametreli bir yardımcı sınıfınız olur. O zaman alacağınız şöyle görünebilir:

get { return StringConverter<DataType>.FromString(base.Value); }

Şimdi, parametreli türlerle ilgili deneyimimin C ++ ve şablonlarıyla sınırlı olduğunu belirtmeliyim, ancak C # jeneriklerini kullanarak aynı tür bir şey yapmanın bir yolu olduğunu hayal ediyorum.


Genel sürümler C # 'da yoktur.
Shimmy Weitzhandler

3

Statiği kontrol edin Nullable.GetUnderlyingType. - Temel alınan tür null ise, template parametresi değildir Nullableve bu türü doğrudan kullanabiliriz - Temeldeki tür null değilse, dönüşümde temel alınan türü kullanın.

Benim için iş gibi görünüyor:

public object Get( string _toparse, Type _t )
{
    // Test for Nullable<T> and return the base type instead:
    Type undertype = Nullable.GetUnderlyingType(_t);
    Type basetype = undertype == null ? _t : undertype;
    return Convert.ChangeType(_toparse, basetype);
}

public T Get<T>(string _key)
{
    return (T)Get(_key, typeof(T));
}

public void test()
{
    int x = Get<int>("14");
    int? nx = Get<Nullable<int>>("14");
}

1

Bob'un cevabından esinlenerek , bu uzantılar null değer dönüşümünü ve tüm ilkel dönüşümleri dördüncü ve dördüncü olarak destekler.

public static class ConversionExtensions
{
        public static object Convert(this object value, Type t)
        {
            Type underlyingType = Nullable.GetUnderlyingType(t);

            if (underlyingType != null && value == null)
            {
                return null;
            }
            Type basetype = underlyingType == null ? t : underlyingType;
            return System.Convert.ChangeType(value, basetype);
        }

        public static T Convert<T>(this object value)
        {
            return (T)value.Convert(typeof(T));
        }
}

Örnekler

            string stringValue = null;
            int? intResult = stringValue.Convert<int?>();

            int? intValue = null;
            var strResult = intValue.Convert<string>();

0
public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

Bir nesne üzerinden dönüştürme kullanıyorum. Biraz daha basit.


teşekkürler Bir arayüzde bir T dönüştürmek zorunda ve basit dönüşüm T nesnesi doğru, kolay ve hızlı çalışır teşekkürler
LXG

5
(int) (nesne), "54"; bir FATALİT!, bu VB değil!
Tomer W

0

Lobos cevabını kullandım ve işe yarıyor. Ama kültür ortamından dolayı iki katına dönüşümle ilgili bir sorunum vardı . Ben de ekledim

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);

0

Yine başka bir varyasyon. Nullables öğesinin yanı sıra dizenin boş ve T'nin boş bırakılmadığı durumları işler.

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get
        {
            if (base.Value == null) return default(T);
            var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
            return (T)Convert.ChangeType(base.Value, type);
        }
        set { base.Value = value.ToString(); }
    }
}

0

Aşağıdaki gibi bir satırda yapabilirsiniz:

YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));

Mutlu kodlama;)


Kodu yanıt olarak paylaştığınızda, lütfen açıklamaya çalışın.
Yunus Temurlenk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.