Как вызвать универсальный с ограничениями, когда тип известен только во время выполнения - PullRequest
2 голосов
/ 10 февраля 2012

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

listProvider.For<AnEnumType>().And<AClass>.GetLists();

, чем

listProvider.ForEnum<AnEnumType>().ForClass<AClass>.GetLists();

Вот пример кода

public class Foo
{
    public void DoSomething<T>
    {
        if(typeof(T).IsEnum)
        {
           //Do Something
        } else if (typeof(T).IsClass)
        {
           var bar = new Bar();

           //Problem How to call bar as type T must be a reference type?
           bar.GetData<T>()
        }     
    }
}

public class Bar
{
    public IProvideList<T> GetData() where T : class
    {
        //Do Something
    }
}

public interface IProvideList<T> T : class
{

}

Во время компиляции компилятор не знает, что T является классом, но я знаю, что это будет во время выполнения.Я могу вызвать это с помощью отражения:

bar.GetType().GetMethod("GetData").MakeGenericMethod(typeof(T));

, однако я не могу привести результат обратно к (IProvideList) при вызове метода, потому что T должен быть referenceType

Есть ли способобойти это?

Ответы [ 3 ]

1 голос
/ 10 февраля 2012

Вы должны использовать where T : class в баре?если нет, попробуйте это.

public class Foo
{
    public void DoSomething<T>()
    {
        if(typeof(T).IsEnum)
        {
           //Do Something
        } else if (typeof(T).IsClass)
        {
           var bar = new Bar();

           //Problem How to call bar as type T must be a reference type?
            bar.GetData<T>();
        }     
    }
}

public class Bar
{
    public IProvideList<T> GetData<T>() //where T : class
    {
        //Do Something
    }
}

public interface IProvideList<T> //where T : class
{

}
1 голос
/ 10 февраля 2012

Вместо Bar вы можете использовать Bar<T>, и все это естественно падает до:

public void DoSomething<T>
{
    if(typeof(T).IsEnum)
    {
       //Do Something
    } 
    else if (typeof(T).IsClass)
    {
       //Here you know T
       var bar = new Bar<T>();
       bar.GetData()
    }     
}

....
public class Bar<T>
{
    public IProvideList<T> GetData<T>() where T : class
    {
        //Do Something
    }
}
0 голосов
/ 10 февраля 2012

Мне в итоге удалось обойти это, сделав рефлексию:

bar.GetType().GetMethod("GetData").MakeGenericMethod(typeof(T));

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

var listProviderType = typeof (IProvideList<>).MakeGenericType(typeof (T));                    
var result = istProviderImplType.GetMethod("MethodINeedToCall").Invoke(listProviderImpl, null);   

Не совсем хороший код, который я знаю, но он достигает желаемого результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...