Генерация общего типа во время выполнения - PullRequest
2 голосов
/ 20 февраля 2011

Мне интересно, возможно ли использовать тип одной переменной для установки в качестве типа другой универсальной переменной?

Например, скажем, у меня есть этот код:

public class Foo: IBar<ushort>
{
    public FooBar()
    {
        Value = 0;
    }

    public ushort Value { get; private set; }
}

У меня также есть этот класс:

public class FooDTO<TType> : IBar<TType>
{
    public TType Value { get; private set; }
}

В этих примерах в интерфейсе для IBar есть свойство

TType Value;

Тогда в моем коде у меня есть

var myFoo = new Foo();
var fooDataType = myFoo.Value.GetType();

//I know this line of code does not compile, but this is what I am looking to be able to do
var myFooDTO= new FooDTO<fooDataType>();

Возможно ли то, что я ищу? Будет ли он слишком медленным для интенсивного использования кода (из-за использования отражения.

Ответы [ 5 ]

2 голосов
/ 21 февраля 2011

Почему бы не использовать вывод типа метода:

public class FooDTO<TType> {
    public TType Value { get; private set; }
}

public class Foo : FooDTO<ushort> { }

static FooDTO<T> GetTypedFoo<T>(T Obj) {
    return new FooDTO<T>();
}

static void Main(string[] args) {
   Foo F = new Foo();

   var fooDTO = GetTypedFoo(F.Value);
}
2 голосов
/ 21 февраля 2011

Вы можете сделать это через Reflection, используя Type.MakeGenericType .

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

1 голос
/ 21 февраля 2011

Всегда, когда я читаю «универсальный» и «время выполнения» в одном предложении, я всегда говорю «плохой дизайн» или «не понимаю, что означает универсальный».Возможно оба.

Общий параметр является неотъемлемой частью типа.Таким образом, поговорка «Генерировать общий тип во время выполнения» такая же, как «Создать класс Foo во время выполнения».Вы либо ищете отражение, либо измените дизайн своего алгоритма.

Также ключевое слово var не поможет вам в этом случае.Забудь об этом.

0 голосов
/ 21 февраля 2011

Ядро того, что вы хотите:

var type = typeof(FooDTO<>).MakeGenericType(fooDataType);
object obj = Activator.CreateInstance(type);

однако, вы заметите, что это отражение, и в значительной степени связывает вас с object. Обычный обходной путь - это иметь доступ к неуниверсальной версии API, чтобы вы могли работать с object - например (с добавлением неуниверсального IBar):

IBar bar = (IBar)Activator.CreateInstance(type);

Вы, конечно, можете переместить хита времени выполнения / генериков выше - возможно, в универсальный метод; тогда все в универсальном методе может использовать T, и вы можете использовать MakeGenericMethod для выполнения этого метода в контексте определенного T, известного только во время выполнения.

0 голосов
/ 21 февраля 2011

Вы ищете отражение во время компиляции, функция, которой нет в C #. Поэтому, если вы ищете оптимизацию производительности, решения хуже, чем проблема.

D имеет эту функцию, хотя; Вы можете легко написать

int x = 0;
typeof(x) y = x + 2;

или даже намного более сложные выражения в D, и все они вычисляются во время компиляции.

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