Передать тип динамически в <T>

Видишь, у меня такая ситуация ...

object myRoledata  = List() --> (some list or Ienumerable type)

Теперь у меня есть универсальный метод, который создает объект XML изList - Что-то вроде этого..

public string GetXML(object listdata)  
{  
    List objLists = (List)Convert.ChangeType(listData, typeof(List));  
    foreach(var obj in listdata)   
    {  
        //logic to create xml  
    }  
}

Теперь, чтобы запустить этот метод, мне нужно сделать так:

string xml = GetXML(myRoledata);

Теперь я не знаю, чтоType может прийти ко мне, чтобы передатьGetXML метод. У меня есть метод, который будет вызыватьGetXML для разныхTypeнапример, ,RolesUsers так далее

теперь я могу получитьType в пределахList как это

Type genericType = obj.GetType().GetGenericArguments()[0];

но не могу передать это так

string xml = GetXML(myRoledata);

Есть ли в любом случае, в котором я могу передать любойgenericTypes вGetXML метод?

 ShuggyCoUk18 авг. 2009 г., 13:08
Вы, вероятно, хотите прояснить в вопросе, неизвестны ли (возможно, несколько) типы T во время компиляции или нет. Если они известны, то УльрикОтвет s имеет смысл, то есть прекратить приведение и вызвать тип аргумента (возможно, с несколькими перегрузками). Если это неизвестно, вы должны использовать рефлексию в той или иной форме, и ответ Маркса показывает самый простой и, вероятно, лучший способ добиться этого.

Ответы на вопрос(5)

но возможно ли переписать вашу функцию как:

public string GetXML<t>(IEnumerable<t> listdata)  
{  
    foreach(var obj in listdata)   
    {  
        //logic to create xml  
    }  
}
</t></t>

Тогда это можно назвать как:

List<role> myList;
GetXML(myList);
</role>

Вы можете добавлять параметры типа настолько далеко, насколько это необходимо для их поддержки, пока не доберетесь до места, которое знает, что такое сплошной тип.

T> в первой строке вашего метода, почему нет просто измените сигнатуру метода на

public string GetXML<t>(List<t> listdata)
</t></t>

Таким образом, вы нечтобы получить общие аргументы, нужно использовать отражение.

РЕДАКТИРОВАТЬ: я вижу, что вы должны иметь возможность принимать IEnumerable коллекций, а не только списки. Итак, рассмотрите возможность изменения подписи вашего метода на

public string GetXML<t>(IEnumerable<t> listdata)
</t></t>

typeof(SomeClass).GetMethod("GetXML").MakeGenericMethod(genericType)
         .Invoke(inst, new object[] {myRoleData});

гдеinst являетсяnull если это статический метод,this для текущего экземпляра (в этом случае вы также можете использоватьGetType() вместоtypeof(SomeClass)) или целевой объект в противном случае.

 Ulrik Rasmussen18 авг. 2009 г., 10:24
Но развет это в корне неправильно? Вызывая метод таким способом, на самом деле нет никакой причины использовать дженерики вообще, потому что вы отбрасываете проверки типов и получаете все свои ошибки во время выполнения.
 Marc Gravell18 авг. 2009 г., 10:31
Моя интерпретация вопроса заключается в том, что они хотели отделить его от дженериков. Если это толкование неверно, то ваш подход явно более уместен. Это зависит от сценария ;-p
Решение Вопроса

избежать Решение. Этоявляется возможно посредством рефлексии вызывать методы динамически, без их статического разрешения, но это как бы побеждает весь смысл аннотаций типов.

Либо сделать это:

public string GetXML(IEnumerable listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}

... который вы теперь можете позвонить с любогоIEnumerableили напишите "современный" путь как:

public string GetXML(IEnumerable<object> listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}
<p>... который вы можете позвонить с любого<code>IEnumerable</code> с помощью<code>GetXML(someEnumerable.Cast<object>()) а в C # 4.0 даже напрямую по ковариации.<p></p><p>Если вам нужен тип элемента времени выполнения, вы можете получить его, используя<code>.GetType()</code> для каждого элемента, или вы можете просто передать его в качестве параметра (и предоставить переопределение для обратной совместимости):</p><pre><code>public string GetXML(Type elementType, IEnumerable<object> listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}

public string GetXML<t>(IEnumerable<t> listdata) {
    return GetXML(typeof(T),listdata.Cast<object>());
}
<p>Кстати, если выПри построении XML, строка, вероятно, является менее надежным выбором типа возврата: если возможно, вы можете работать с чем-то вроде<code>XElement</code> вместо этого - и получите гарантию xml-validitys для загрузки.</p></object></t></t></object></code></pre></object></code></p></object>
 Eamon Nerbonne25 авг. 2009 г., 16:33
В любом случае спасибо за комментарий - не универсальныйIEnumerable это тоже хороший выбор.
 Matthew Scharley25 авг. 2009 г., 16:18
На самом деле я'буду советовать не использоватьIEnumerable непосредственно, по крайней мере, до C # 4.0; это, вероятно, выигралделать то, что вы хотите, из-за отсутствия дисперсии параметров типа.IEnumerable более чем годный к употреблению.
 Eamon Nerbonne25 авг. 2009 г., 16:32
Что ж, специально для IEnumerable, ковариация является меньшей проблемой из-за Linq.Cast оператор. Если вы хотите вызвать метод сIEnumerable параметр, и у вас естьIEnumerable myEnum с некоторымиT != objectможно просто сделатьmyEnum.Cast() с небольшой потерей читаемости и скорости. Стилистический недостаток неуниверсальногоIEnumerable это отсутствие явногоIDisposable поддержка, тот факт, чтоSystem.Collections не входит в набор значений по умолчанию, которые VS.NET добавляет в новые файлы, и чтоменее распространенная идиома.

но вы используете неправильный метод. Посмотрите на Type.MakeGenericType или MethodInfo.MakeGenericMethod. Это займет несколько строк, чем ваш пример, но это должно быть легко решить.

GetGenericArguments () можно использовать для получения типа ролей из списка. Это'С другой стороны.

Кстати: похоже, вы внедрили какую-то сериализацию XML. Убедитесь, что вы проверили существующие классы, прежде чем изобретать велосипед. ;-)

Ваш ответ на вопрос