在没有反射的情况下实例化任意类型
我错了。似乎有很多方法可以在没有真正反射的情况下实例化类型。我会尽量整理一份我能找到的所有东西的清单。
泛型
根据您想要做的事情,您也许可以使用一种非常酷的技术,称为泛型。您不能在运行时输入任意类型的名称,因此这不一定能完全回答您的问题,但如果您在编译时知道所需的类型,这将是一个很棒的工具。 这不涉及任何形式的反射,而是完全在编译时。这是一个例子:
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;
}
}
Lambda 字典
感谢 Anthony Pegram 在这方面的天才(见下面的 cmets)。以前我使用反射来解决这个问题,但由于 lambda 表达式,他将其修复为无需任何反射即可工作。
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 });