目录
Ⅰ 使用【接口】 约束 T ,令它只能是若干 Box 中的一种 Box
Ⅱ 使用【反射】,令GetBox 中仍然可以使用 T 的构造函数并返回 T 类型的实例对象
场景简介
这是你自定义的KeySelectBox类型
public class KeySelectBox
{
public KeySelectBox()
{
}
}
这是你自定义的BoxObject类型
public class BoxObject
{
public static T GetBox<T>()
{
}
}
BoxObject表示对所有Box的统筹,你可以定义KeySelectBox、TextBox……这样的Box。
接着,统一调用泛型函数GetBox<T>来获取指定类型的Box.
运用示例
Ⅰ 使用【接口】 约束 T ,令它只能是若干 Box 中的一种 Box
(1)添加一个名为 Box 的【接口】
public interface Box
{
}
(2)所有自定义的 Box 都去实现这个【接口】,这里以KeySelectBox为例
public class KeySelectBox : Box
{
public KeySelectBox() { }
}
(3)用【接口】来约束泛型函数 GetBox<T>
public static T GetBox<T>() where T : Box
{
}
如此一来,GetBox<T> 的 T 就只能填入指定的自定义类型了!
Ⅱ 使用【反射】,令GetBox<T> 中仍然可以使用 T 的构造函数并返回 T 类型的实例对象
这个在开发类库的时候有用,因为有些类型是你不希望能在类库外被直接实例化的,你希望通过某个泛型函数来统一这些类型的调度,你可能会把它们的构造函数设置为 【internal】 的,但这么做的话,你将无法使用 【where T : new()】因为new()约束要求 【public、无参】 构造函数,自然,你也无法执行下述操作:
T target = new T();
这个时候就该【反射】排上用场啦!
public static T GetBox<T>() where T : Box
{
ConstructorInfo? constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null);
//反射 T 的无参构造函数信息
if (constructor == null) { throw new InvalidOperationException($"您尝试获取的{typeof(T).Name}组件不存在构造函数!"); }
//若未能反射到无参构造函数,则抛出异常
T result = (T)constructor.Invoke(null);
//获取成功,则调用 T 的构造函数
return result;
}
至此,你的类库将只允许使用者通过统一的泛型函数 GetBox<T> 来获取你在类库中定义类型的实例对象。
当然,你也许注意到了,这里的【接口】是【public】,这意味着,使用这个类库的人,一样可以定义自己的 Box ,只需实现 【Box接口】,就能同样使用 GetBox<T> 了。
个人认为,这种设计能使类型的管理更清晰,使用过程更安全,也具备不错的可拓展性!