我想为通用约束限制的某种类型的类提供工厂,但是我需要确保要创建的 product 具有某个构造函数以使我的工厂工作
public interface IFactory<TProduct>
where TProduct: class, IMyRestriction
{
TProduct Create();
}
实现IMyRestriction的类:
public class MyRestriction : IMyRestriction {
public MyRestriction(IArgumentType1 arg1, IArgumentType2 arg2) {
...
}
}
这将使这项工作......
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct: class, IMyRestriction
{
public TProduct Create() {
// args provided by factory constructor
Activator.CreateInstance(typeof(TProduct), arg1, arg2);
}
}
...但不适用于这样的课程:
public class MyDerivedRestriction : MyRestriction {
public MyDerivedRestriction()
: base(null, null)
{
}
}
我能够使用泛型限制某个构造函数的唯一方法是使用new()约束,但在这种情况下这没有意义。
答案 0 :(得分:2)
你基本上回答了你自己的问题 - 你知道控制构造函数的唯一约束类型是无参数的。
剩下的唯一选择是使用某种初始化方法代替构造函数,并且通常在构造函数中执行的逻辑在Init
方法中执行
interface IMyRestriction
{
// use whichever arguments you wanted for construction
void Init(string myParam1, string myParam2)
}
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct: class, IMyRestriction, new()
{
public TProduct Create() {
TProduct p = new TProduct();
p.Init(arg1,arg2);
return p;
}
}
答案 1 :(得分:2)
如果您需要使用不同的构造函数签名创建不同的类,您可能正在寻找Abstract Factory模式,其中每个实体类都有自己的Factory接口实现:
#region Restriction Types
public class MyRestriction : IMyRestriction {
public MyRestriction(IArgumentType1 arg1, IArgumentType2 arg2) {
...
}
}
public class MyDerivedRestriction : MyRestriction {
public MyDerivedRestriction()
: base(null, null)
{
}
}
#endregion
#region Factory interface
public interface IFactory<TProduct>
where TProduct: class, IMyRestriction
{
TProduct Create();
}
#endregion
#region Factory implementations for each entity
public class MyRestrictionFactory : IFactory<MyRestriction>
{
public MyRestriction Create()
{
// args provided by factory constructor
return new MyRestriction(arg1, arg2);
}
}
public class MyDerivedRestrictionFactory : IFactory<MyDerivedRestriction>
{
public MyDerivedRestriction Create()
{
return new MyDerivedRestriction();
}
}
#endregion
这似乎可以创建更多的代码,但每个工厂类都可以很小,而且它提供更多的类型安全性并且更灵活,因为工厂可以处理其实体的特性。
作为这种模式的扩展,人们经常为每个工厂添加接口,以便更好地在IOC容器中注册并提供更多抽象,但在您的情况下可能不需要这样做。例如:
// this gets resolved in DI, so the IFactory<T> part is abstracted away
public interface IMyRestrictionFactory
{
MyRestriction Create();
}
public class MyRestrictionFactory : IFactory<MyRestriction>, IMyRestrictionFactory
{
public MyRestriction Create()
{
// args provided by factory constructor
return new MyRestriction(arg1, arg2);
}
}
答案 2 :(得分:0)
在C#中,除了new()
(无参数构造函数)之外,你不能放置定义构造函数所需签名的泛型约束。
你可以做的最好的事情是依赖运行时异常,或者重写初始化逻辑以使用IMyRestriction
的属性而不是构造函数参数:
interface IMyRestriction
{
IArgumentType1 Property1 { get; set; }
IArgumentType2 Property2 { get; set; }
}
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct : class, IMyRestriction, new()
{
public TProduct Create()
{
var product = new TProduct();
product.Property1 = arg1;
product.Property2 = arg2;
return product;
}
}