2013-03-06 2 views
0

У меня есть интерфейс:Out общие параметры с типами известны только во время выполнения

public interface IOut<T> 
{ 
    void Get(out T output); 
} 

и класс, который реализует это:

public class Impl : IOut<string>, IOut<int>{ 
    public void Get(out string output) { output = "string"; } 
    public void Get(out int output) { output = 12; } 
} 

я могу сделать очень хорошо следующее:

public static void Main() 
{ 
    dynamic dImpl = new Impl(); 

    string sOutput; 
    int iOutput; 

    dImpl.Get(out sOutput); 
    dImpl.Get(out iOutput); 

    Console.WriteLine(sOutput); 
    Console.WriteLine(iOutput); 
} 

Моя проблема в том, что я знаю только тип, который мне нужен, чтобы получил во время выполнения, так как I хотят назвать мой Get код следующим образом:

public static void Main() 
{ 
    dynamic dImpl = new Impl(); 

    var t = typeof(string); 
    t output; 
    dImpl.Get(out output); 

    Console.WriteLine(output); 
} 

Теперь я знаю, что это не будет работать, и я попытался рефлекторно выполняя В ролях:

public static T Cast<T>(object o) { return (T) o; } 

но я у меня нет объекта для броска, у меня есть только Type. Я пробовал по умолчанию:

public static T Default<T>() { return default(T); } 

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

var method = typeof(Program).GetMethod("Default").MakeGenericMethod(typeof(string)); 
var defaulted = method.Invoke(null, null); 

defaulted собирается быть пустым, и при вызове dImpl.Get(out defaulted) среда выполнения не уверен в том, какую перегрузку использовать.

Итак, что я ищу либо: а) каким-то образом сделать это, используя текущую настройку интерфейса [предпочтительная] б) другой способ достижения целей

ответ

2

Вы можете получить метод вызова от типа интерфейса, а не реализующего типа:

object[] parameters = new object[] { null }; 
Type typeParam = typeof(string); 
Type ifaceType = typeof(IOut<>).MakeGenericType(typeParam); 
MethodInfo method = ifaceType.GetMethod("Get"); 

var impl = new Impl(); 
method.Invoke(impl, parameters); 

object outParam = parameters[0]; 
+0

Это здорово, я бы не думал о том, на это таким образом. –

+0

, где происходит 'impl' в' method.Invoke (impl, parameters) '? – bflemi3

+0

@ bflemi3 - Это просто экземпляр класса «Impl». Я обновил ответ. – Lee

0

Если вы не знаете, тип output до выполнения, вы не можете объявить его строго типизированный экземпляр на C#.

Если вы можете сделать логику вызова (Main в вашем примере), общий на T тоже, это сработает - но это только отменит вашу проблему.

Другой вариант - объявить output в качестве базового класса или интерфейса и ограничить общий T. Использование object в качестве базового класса может работать для вас - зависит от того, что вы хотите с ним делать.

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