Полное отражение будет:
return (Interface2<T>)Activator.CreateInstance(typeof(Class1<>).MakeGenericType(typeof(T)));
, но оно медленное (медленнее по сравнению с new Foo()
) ... Я не нахожу другого пути.Обратите внимание, что вы уже частично двигаетесь в направлении отражения (IsAssignableFrom
)
Мммм, используя "кэширование" статических классов, мы можем немного обмануть ... Мы можем произвести во время выполнения точный необходимый коддля создания new Class1<T>
и его кеширования.
Первая версия
static class Maker<T>
{
public static Func<Interface2<T>> Func { get; private set; }
public static Interface2<T> New()
{
if (Func == null)
{
Func = Expression.Lambda<Func<Interface2<T>>>(Expression.New(typeof(Class1<>).MakeGenericType(typeof(T)))).Compile();
}
return Func();
}
}
Я использую дерево выражений, которое выполняет new Class1<T>
.Тогда:
static Interface2<T> GetObject<T>()
{
if (typeof(Interface1).IsAssignableFrom(typeof(T)))
{
return Maker<T>.New();
}
return new Class2<T>();
}
Но все же мы можем сделать что-то большее.Учитывая тип T
, результат if
в GetObject()
может быть предварительно рассчитан и кэширован.Мы перемещаем целое GetObject()
внутри дерева выражений.
static class Maker2<T>
{
public static Func<Interface2<T>> Func { get; private set; }
public static Interface2<T> New()
{
if (Func == null)
{
if (typeof(Interface1).IsAssignableFrom(typeof(T)))
{
Func = Expression.Lambda<Func<Interface2<T>>>(Expression.New(typeof(Class1<>).MakeGenericType(typeof(T)))).Compile();
}
else
{
Func = Expression.Lambda<Func<Interface2<T>>>(Expression.New(typeof(Class2<>).MakeGenericType(typeof(T)))).Compile();
}
}
return Func();
}
}
, а затем
static Interface2<T> GetObject2<T>()
{
return Maker2<T>.New();
}
Решение, использующее дерево выражений, очень медленное при первом использовании для каждоговведите T
, потому что он должен создать дерево выражений и скомпилировать его, но тогда это становится очень быстрым.Это по сравнению с версией, которая использует Activator.CreateInstance
, которая каждый раз работает медленно: -)