سؤال

كيف يمكنني التحويل إلى Nullable من سلسلة باستخدام الانعكاس؟

لدي التعليمات البرمجية التالية للتحويل إلى أي نوع قيمة تقريبا معطى أي قيمة تقريبا. هناك عدد كبير جدا من التعليمات البرمجية أعلاه لاستخدام isassignablefrom، وما إلى ذلك، لذلك هذا هو الملاذ الأخير.

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

if (parse != null)
{
    object parsed = parse.Invoke(null, new object[] { value.ToString() });
    return (T)parsed;
}
else
{
    throw new InvalidOperationException("The value you specified is not a valid " + typeof(T).ToString());
}

المشكلة تأتي عندما أريد تحويلها إلى نوع غير قابلة للطول مثل فترة طويلة؟

من الواضح، الطويل؟ فئة ليس لديها طريقة تحليل.

كيف استخراج طريقة التحليل من nullable قالب اكتب؟

تعديل:

إليك بطارية قصيرة من الاختبارات التي أحاول تمريرها:

[Test]
public void ConverterTNullable()
{
    Assert.That((int?)1, Is.EqualTo(Converter<int?>.Convert(1)));
    Assert.That((int?)2, Is.EqualTo(Converter<int?>.Convert(2.0d)));
    Assert.That(3, Is.EqualTo(Converter<long>.Convert(3)));

    Assert.That((object)null, Is.EqualTo(Converter<long?>.Convert("")));
    Assert.That((object)null, Is.EqualTo(Converter<long?>.Convert(null)));
    Assert.That((object)null, Is.EqualTo(Converter<long?>.Convert(DBNull.Value)));

    Assert.That((long)1, Is.EqualTo(Converter<long?>.Convert("1")));
    Assert.That((long)2, Is.EqualTo(Converter<long?>.Convert(2.0)));
    Assert.That((long?)3, Is.EqualTo(Converter<long>.Convert(3)));
}

والوظيفة كلها:

/// <summary>
/// Converts any compatible object to an instance of T.
/// </summary>
/// <param name="value">The value to convert.</param>
/// <returns>The converted value.</returns>
public static T Convert(object value)
{
    if (value is T)
    {
        return (T)value;
    }

    Type t = typeof(T);

    if (t == typeof(string))
    {
        if (value is DBNull || value == null)
        {
            return (T)(object)null;
        }
        else
        {
            return (T)(object)(value.ToString());
        }
    }
    else
    {
        if (value is DBNull || value == null)
        {
            return default(T);
        }

        if (value is string && string.IsNullOrEmpty((string)value))
        {
            return default(T);
        }

        try
        {
            return (T)value;
        }
        catch (InvalidCastException)
        {
        }

        if (Nullable.GetUnderlyingType(t) != null)
        {
            t = Nullable.GetUnderlyingType(t);
        }

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

        if (parse != null)
        {
            object parsed = parse.Invoke(null, new object[] { value.ToString() });
            return (T)parsed;
        }
        else
        {
            throw new InvalidOperationException("The value you specified is not a valid " + typeof(T).ToString());
        }
    }
}
هل كانت مفيدة؟

المحلول 3

أضفت هذا الشيء قليلا:

if (Nullable.GetUnderlyingType(t) != null)
{
    t = Nullable.GetUnderlyingType(t);
}

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

شكرا لكم جميعا!

نصائح أخرى

ربما كنت أستخدم TypeConverter في هذه الحالة، و Nullable.GetUnderlyingType(); ؛ مثال على الطريق ...

    static void Main()
    {
        long? val1 = Parse<long?>("123");
        long? val2 = Parse<long?>(null);
    }

    static T Parse<T>(string value)
    {
        return (T) TypeDescriptor.GetConverter(typeof(T))
            .ConvertFrom(value);
    }

هذا ينبغي أن الوظيفة. (يتم تضمين الرمز بطريقة تمديد للبساطة، على الرغم من أنه قد لا يكون ما تريد.)

public static T? ParseToNullable<T>(this string value) where T : struct
{
    var parseMethod = typeof(T).GetMethod("Parse", new Type[] { typeof(string) });
    if (parseMethod == null)
        return new Nullable<T>();

    try
    {
        var value = parseMethod.Invoke(null, new object[] { value.ToString() });
        return new Nullable<T>((T)value);
    }
    catch
    {
        return new Nullable<T>();
    }
}

الآن، إذا كنت تريد العلامة النوع العام بحد ذاتها أن تكون النوع المطلقة بدلا من الاسم الأساسي (لا أرى حقا ميزة في هذا)، يمكنك الاستفادة منها:

Nullable.GetUnderlyingType(typeof(T))

كما اقترح مارك جرافيل، فإنه سيطلب سوى بعض التعديلات الطفيفة على التعليمات البرمجية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top