Создание произвольного типа без отражения
Я был не прав.Казалось бы, существует множество способов создать экземпляр типа без истинного отражения.Я постараюсь составить список всего, что смогу найти.
Дженерики
В зависимости от того, что вы пытаетесь сделать, вы можете использовать очень классную технику, которая называется дженерики.Вы не можете вводить произвольное имя типа во время выполнения, так что это не обязательно отвечает на ваш вопрос полностью, но если вы знаете типы, которые вы хотите во время компиляции, это делает отличный инструмент. Это не включает никакого отражения любого вида, но это полностью время компиляции.Вот пример:
interface IParsable
{
bool TryParse(string text);
}
class MyInt : IParsable
{
public int Value { get; private set; }
public static MyInt Parse(string text)
{
Parser parser = new Parser();
return parser.Parse<MyInt>(text);
}
}
class MyFloat : IParsable
{
public float Value { get; private set; }
public static MyFloat Parse(string text)
{
Parser parser = new Parser();
return parser.Parse<MyFloat>(text);
}
}
class Parser
{
// The "new()" constraint means that T must have a
// parameterless constructor.
private T Parse<T>(string text)
where T : IParsable, new()
{
// Even though T isn't actually a type, we can use
// it as if it were, for the most part.
T obj = new T();
// Because we had the IParsable constraint, we can
// use the TryParse method.
if (!obj.TryParse(text))
{
throw new Exception("Text could not be parsed.");
}
return obj;
}
}
Словарь Ламбдаса
Благодарю Энтони Пеграма за его гениальность (см. Комментарии ниже).Ранее у меня было это с помощью отражения, но он исправил его, чтобы он работал без каких-либо отражений, благодаря лямбда-выражениям.
static readonly IDictionary<string, Func<object>> Types = new Dictionary<string, Func<object>>()
{
{ "TypeA", () => new TypeA() },
{ "TypeB", () => new TypeB() },
{ "TypeC", () => new TypeC() },
};
// If you're okay with a bit of reflection behind-the-scenes, change "object"
// here to "dynamic", and you won't have to cast down the road.
object void GetInstance(string name)
{
if (Types.ContainsKey(name))
{
return Types[name]();
}
else
{
return null;
}
}
Предварительно созданные объекты
Еще один вариант - вернутьОдна и та же ссылка каждый раз.Это полностью исключает «истинное» отражение.Эта идея повторного использования экземпляров имеет некоторые важные последствия, которые могут быть как хорошими, так и плохими, в зависимости от того, что вы делаете.Эти последствия очень интересны и могут быть весьма удивительными при правильном использовании.
Вы можете, если хотите, каждый тип реализовать конкретный интерфейс и привести к нему вместо возврата необработанного объекта.
static readonly IDictionary<string, object> Instances = new Dictionary<string, object>()
{
{ "TypeA", new TypeA() },
{ "TypeB", new TypeB() },
{ "TypeC", new TypeC() },
};
object void GetInstance(string name)
{
if (!Instances.ContainsKey(name))
{
return null;
}
return Instances[name];
}
Создание произвольного типа с помощью отражения
У вас есть хороший набор ответов, которые будут отлично работать, если у вашего типа есть конструктор без параметров.Но что, если это не так?
const string TYPE = "System.String";
Type type = Type.GetType(TYPE);
if (type == null)
{
// Type doesn't exist--at least, not in mscorlib or current assembly,
// or we didn't specify the assembly.
throw new Exception("Could not find type " + TYPE + ".");
}
// Note the Type array. These are the types of the parameters that the
// constructor takes.
ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(char), typeof(int) });
if (ctor == null)
{
// Constructor doesn't exist that takes those parameters.
throw new Exception("Could not find proper constructor in " + TYPE + ".");
}
// Note the object array. These are the actual parameters passed to the
// constructor. They should obviously match the types specified above.
string result = (string)ctor.Invoke(new object[] { 'a', 5 });