2015-12-30 1 views
5

У меня есть удивительно уродливый метод, который должен вытащить различные данные из базы данных и использовать его для построения объекта запрашиваемого типа. Цель состоит в том, чтобы вытащить разнообразное уродство в одно место, так что классы, которые происходят из класса, содержащего этот метод, могут быть относительно чистыми.Как передать объект в общий тип возвращаемого значения, когда тип возврата является общим интерфейсом?

Я не имею проблему с тем, когда он должен возвращать один объект, даже если тип обнуляемым:

protected T getValue<T>(ParameterObject myParameterObject) 
{ 
    var typeOfT = typeof (T); 

    if (typeOfT == typeof(bool)) 
    { 
     string val = this.getValue(myParameterObject); 

     if (val == null) 
      return default(T); 

     bool rVal; 
     if (!Boolean.TryParse(val, out rVal)) 
      return default(T); 

     return changeType<T>(rVal); 
    } 

    if (typeOfT == typeof (double?)) 
    { 
     string val = this.getValue(myParameterObject); 

     if (val == null) 
      return default(T); 

     double rVal; 
     if (!Double.TryParse(val, out rVal)) 
      return default(T); 

     return changeType<T>(rVal); 
    } 

    [...] 
} 

public static T changeType<T>(object value) 
{ 
    var t = typeof(T); 
    if (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Nullable<>)) 
     return (T)Convert.ChangeType(value, t); 

    if (value == null) 
     return default(T); 

    t = Nullable.GetUnderlyingType(t); 
    return (T)Convert.ChangeType(value, t); 
} 

К сожалению, у меня есть случаи, в которых мой желаемый возвращаемый тип IList, где Я хочу вернуться в список:

protected T getValue<T>(ParameterObject myParameterObject) 
{ 
    var typeOfT = typeof (T); 

    if (typeOfT.IsGenericType) 
    { 
     if (typeOfT.GetGenericTypeDefinition() == typeof (IList<>)) 
     { 
      var genericArgumentType = typeOfT.GenericTypeArguments.FirstOrDefault(); 
      var baseType = typeof (List<>); 
      var genericType = baseType.MakeGenericType(new[] {genericArgumentType}); 

      var rVal = Activator.CreateInstance(genericType); 

      [code to populate the list] 

      return changeType<T>(rVal); 
     } 

    [...] 
} 

Я не могу вернуться в RVal, потому что это объект, а не экземпляр T. Но функция моя changeType() терпит неудачу с ошибкой:

System.InvalidCastException: Object must implement IConvertible.

Итак, у меня есть общий метод, для которого тип возврата является IList, и у меня есть объект, который является List, но моя ссылка на него имеет тип Object. Как это сделать, чтобы я мог вернуть его из функции?

+2

Извините, если мне не хватает чего-то очевидного, но почему вы делаете 'return changeType (rVal);' вместо 'return (T) (object) rVal;'? – 31eee384

ответ

1

Ваша линия return (T)Convert.ChangeType(value, t); не работает, потому что ваш объект value не реализует IConvertible.

От MSDN docs

[...] For the conversion to succeed, value must implement the IConvertible interface, because the method simply wraps a call to an appropriate IConvertible method. The method requires that conversion of value to conversionType be supported.

Чтобы это исправить, я не уверен в общих чертах, но и для конкретного случая value существ с IEnumerable или IEnumerable<> типа, то вы можете попробовать бросить затем выполнить value.Select(x => changeType<ListGenT>(x)) запрос linq. Используя рекурсивно метод , он также должен обрабатывать вложенные общие типы.

+0

Я все еще не уверен, что понимаю, но если я изменил свои методы, чтобы вернуть список , вместо создания списка и возврата IList проблема исчезла. –

 Смежные вопросы

  • Нет связанных вопросов^_^