通用工厂 - 期望某些构造函数

时间:2014-10-07 07:51:26

标签: c# generics factory

我想为通用约束限制的某种类型的类提供工厂,但是我需要确保要创建的 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()约束,但在这种情况下这没有意义。

3 个答案:

答案 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;
    }

}