Получить перечислитель для универсального объекта

Я провел тщательный поиск ответа и не нашел его.

Я хочу написать метод, который переводит объект в объект словаря. При вызове этого метода будет предоставлен конкретный тип входного объекта.

Вот что у меня есть до сих пор.

public static Dictionary<string, string> TranslateFormData<T>(Object form)
{
    T formData = (T)Convert.ChangeType(form, typeof(T));
    Dictionary<string, string> data = new Dictionary<string, string>();
    IEnumerator<KeyValuePair<string, string>> pairs = formData.GetEnumerator();

    while (pairs.MoveNext())
    {
        //Code left out for brevity
    }

    return data;
}

Использование будет примерно таким

Dictionary<string,string> data = FormData.TranslateFormData<FormCollection>(formData);

Однако в методе TranslateFormData строка

IEnumerator<KeyValuePair<string, string>> pairs = formData.GetEnumerator ( );

выдает следующую ошибку:

«T» не содержит определения для «GetEnumerator», и не удалось найти метод расширения «GetEnumerator», принимающий первый аргумент типа «T» (вам не хватает директивы using или ссылки на сборку?)

Как я могу указать Тип для формы объекта, чтобы получить перечислитель?


person Paul Stoner    schedule 05.11.2014    source источник


Ответы (2)


Во-первых, просто сделайте параметр типа T, чтобы избежать приведения:

public static Dictionary<string, string> TranslateFormData<T> ( T formData )

Затем вы можете добавить общее ограничение, чтобы что T должен реализовать IEnumerable< KeyValuePair< string, string > >:

public static Dictionary<string, string> TranslateFormData<T> ( T formData ) 
    where T : IEnumerable<KeyValuePair<string, string>>
{
    // don't need this line due to above
    //T formData = ( T )Convert.ChangeType ( form, typeof ( T ) );

    // rest the same.
}
person clcto    schedule 05.11.2014
comment
Это сработало отлично, но затем создало другую ошибку. В связи с этим я задам другой вопрос, относящийся к следующему выпуску. Спасибо - person Paul Stoner; 05.11.2014
comment
На самом деле, теперь, когда я об этом думаю, вы можете просто иметь метод: public static Dictionary<string,string> TranslateFromData( IEnumerable<KeyValuePair<string,string> formData ) и вообще не использовать дженерики. - person clcto; 05.11.2014
comment
Спасибо за обновление. Тем не менее, я хотел бы сохранить его как можно более общим. Эта функция может быть полезна для перевода других типов. Однако для моей конкретной ситуации я попробую это. Я хочу избежать перегрузки, если это вообще возможно - person Paul Stoner; 05.11.2014
comment
@PaulStoner не будет никакой функциональной разницы. Как с решением в ответе, так и с комментарием вы можете вызывать функцию только с IEnumerable<KeyValuePair<string,string>> - person clcto; 05.11.2014
comment
ОК Это имеет смысл. Возможно, link этот вопрос прольет свет на мою конкретную ситуацию. - person Paul Stoner; 05.11.2014

Есть проблема с тем, что вы спрашиваете, вы в основном пытаетесь заставить объект реализовать интерфейс IEnumerable. Компилятор не знает, будет ли объект, который вы пытаетесь преобразовать, определенно иметь тип IEnumerable.

Для этого вы должны объявить общий объект как объект, реализующий указанный интерфейс.

просто добавьте эту строку в конец объявления вашей функции.

where T : IEnumerable
person Noxymon    schedule 05.11.2014