2

うまくいけば、十分に単純な質問ですが、答えを見つけるのに苦労しています。

「オブジェクト」を「タイプ」オブジェクトで定義されたタイプにキャストするにはどうすればよいですか。

たとえば、基本的に、リフレクションを使用して次のことを行い、可能な限り一般的にしようとしています。

public class MyClass
{
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }
}


public T FillMyClass<T>() where T : new()
{
    //The definitions here are suppled in code - each class we want to work with needs to be "mapped".
    string name1 = "Prop1";
    Type type1 = typeof(string);
    string name2 = "Prop2";
    Type type2 = typeof(int);

    //The values always start out as a string because of the way I'm receiving it.
    string val1 = "test";
    string val2 = "1";

    T t= new T();

    //Works fine, because val1 is already a string
    t.GetType().GetProperty(name1).SetValue(t, val1, null);

    //Having trouble with the below.
    object o = Convert.ChangeType(val2, type2);

    //Fails because o is not an int
    t.GetType().GetProperty(name2).SetValue(t, o, null);

}

したがって、タイプはユーザーによって定義されます (または、プロパティのタイプを検索するだけでも可能です)。しかし、オブジェクトを [Type] にキャストする方法がわかりません。

4

1 に答える 1

2

私もこの問題に数回遭遇しました。この問題にはもっと洗練された解決策があると確信していますが、次の拡張メソッドを作成して、99% の方法で問題を解決しました。

    public static object TryConvertToType(this object source, Type destinationType, object defaultValue = null)
    {
        try
        {
            if (source == null)
                return defaultValue;

            if (destinationType == typeof(bool))
            {
                bool returnValue = false;

                if (!bool.TryParse(source.ToString(), out returnValue))
                {
                    return Convert.ChangeType(source.ToString() == "1", destinationType);
                }
                else
                {
                    return Convert.ChangeType(returnValue, destinationType);
                }
            }
            else if (destinationType.IsSubclassOf(typeof(Enum)))
            {
                try
                {
                    return Enum.Parse(destinationType, source.ToString());
                }
                catch
                {
                    return Enum.ToObject(destinationType, source);
                }
            }
            else if (destinationType == typeof(Guid))
            {
                return Convert.ChangeType(new Guid(source.ToString().ToUpper()), destinationType);
            }
            else if (destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                Type genericType = destinationType.GetGenericArguments().First();

                return Convert.ChangeType(source, genericType);
            }
            else if (source.GetType().IsSubclassOf(destinationType))
            {
                return Convert.ChangeType(source, destinationType);
            }
            else if (!source.GetType().IsValueType
                && source.GetType() != typeof(string)
                && destinationType == typeof(string))
            {
                return Convert.ChangeType(source.GetType().Name, destinationType);
            }
            else
            {
                return Convert.ChangeType(source, destinationType);
            }
        }
        catch
        {
            return defaultValue;
        }
    }

基本的に、使用法では、次のように機能します。

t.GetType().GetProperty(name).GetValue(t, null).TryConvertToType(type2, 0);
于 2012-10-30T16:50:46.760 に答える