用于自动创建具体类的泛型类

时间:2011-10-21 15:58:32

标签: c# .net generics default-implementation

有没有办法接受界面,比如说:

/// <summary>
/// Interface containing operators which operate on T
/// </summary>
public interface IScalarOperators<T>
{
    // Adds two T objects
    IOperateScalar<T> OperatorAdd { get; }
    // Subtracts two T objects
    IOperateScalar<T> OperatorSubtract { get; }
    // Multiplies two T objects
    IOperateScalar<T> OperatorMultiply { get; }
}

// Class containing all the Scalar operators for a given T
class ScalarOperators<T> : IScalarOperators<T>
{
    public IOperateScalar<T> OperatorAdd { get; private set; }
    public IOperateScalar<T> OperatorSubtract { get; private set; }
    public IOperateScalar<T> OperatorMultiply { get; private set; }
    private ScalarOperators(IOperateScalar<T> add, IOperateScalar<T> subtract, IOperateScalar<T> multiply)
    {
        this.OperatorAdd = add;
        this.OperatorSubtract = subtract;
        this.OperatorMultiply = multiply;
    }

    public static ScalarOperators<bool> CreateBool()
    {
        return new ScalarOperators<bool>(new AddBool(), new SubtractBool(), new MultiplyBool());
    }

    public static ScalarOperators<int> CreateInt()
    {
        return new ScalarOperators<int>(new AddInt(), new SubtractInt(), new MultiplyInt());
    }

    // METHOD I WANT TO ADD
    public static ScalarOperators<T> Create()
    {
      // if T == bool
      // return CreateBool()
      // if T == int
      // return CreateInt()
      // else (no definition available for T)
      // return null
    }

    // I tried something like below, but it didn't work...
    public static ScalarOperators<T> Create<T>() where T: bool
    { return CreateBool(); }

    public static ScalarOperators<T> Create<T>() where T : int
    { return CreateInt(); }

    public static ScalarOperators<T> Create<T>()
    { return null; }
}

注意,我想要一个通用的Create方法来创建正确的运算符集,但我不知道该怎么做。

我想用它来从这个方法中删除参数:

    public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other, IScalarOperators<T> operators)
    {
        JoinCells<T> joiner = new JoinCells<T>();
        return joiner.Join(matrix, other, null, operators.OperatorAdd);
    }

变为

    public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other)
    {
        JoinCells<T> joiner = new JoinCells<T>();
        return joiner.Join(matrix, other, null, ScalarOperators<T>.Create().OperatorAdd);
    }

感谢您的帮助!主要是,我只是不想将scalarOperator对象传递给扩展方法,我更倾向于使用'default',因为ScalarOperators不太可能针对定义的任何T进行更改。

3 个答案:

答案 0 :(得分:3)

我建议建立一个IScalarOperators工厂而不是静态类(如果你真的需要它是静态的,你可以通过静态字段访问它)。 你可以在app启动时注册它们并通过这个例子得到它们:

 public IScalarOperators<T> Create<T>()
 {
    // check if exists in dictionary
    return (ScalarOperators<T>)dict[typeof(T)];
 }

dict将是Dictionary类型。 可以通过创建新的实现类并在工厂中注册来在应用程序增长期间添加新的IScalarOperator,这是一个缺点。此外,您将更好地分离关注点(在我看来)更清晰的代码。

答案 1 :(得分:2)

您需要做的是获取T的类型。

您的Create方法可能是这样的:

public static ScalarOperators<T> Create()
{
    Type type = typeof(T); 
    if(type == typeof(bool))
      return CreateBool()
    if(type == typeof(int))
      return CreateInt()
    else
      return null
}

答案 2 :(得分:1)

我认为应该解决这里发生的一些事情。您试图将自定义运算符与它们运行的​​类型隔离开来,这很令人困惑,您正试图采用非常广泛的泛型概念,然后将它们专门化。

对于第一个,你总是会使用相同类型的相同运算符(至少,你永远不会尝试在int类型上使用bool运算符)。没有理由通过为它们设置单独的类来使事情复杂化。对于后者,泛型类和泛型方法对于任何给定的T都是相同的。当然,你很可能在静态工厂方法中得到typeof(T)并与几个特定情况的那个进行比较,然后你由于这个过于复杂的通用操作数结构,必须为每个要处理的新T改变它。

我建议为您的操作数创建一个通用接口,然后为这些类型实现一个包装器。例如,int可以像这样包装。

public interface IScalarOperators<T>
{
    IScalarOperators<T> Add (IScalarOperators<T> rightSide);
    IScalarOperators<T> Subtract (IScalarOperators<T> rightSide);
    IScalarOperators<T> Multiply (IScalarOperators<T> rightSide);
    T Unwrap();
}

public interface IMatrix<T> where T : IScalarOperators<T> { /* whatever */ }

public class CustomInt : IScalarOperators<CustomInt>
{
    private readonly int number;
    public CustomInt(int number) { this.number = number; }
    public CustomInt Unwrap() { return this; }
    public IScalarOperators<CustomInt> Add(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number + rightSide.Unwrap().number); }
    public IScalarOperators<CustomInt> Subtract(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number - rightSide.Unwrap().number); }
    public IScalarOperators<CustomInt> Multiply(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number * rightSide.Unwrap().number); }
}

此时,您可以通过IMatrix<CustomInt>界面操作IScalarOperators<T>并执行所需的任何公开操作。作为一个粗略的例子,假设你有一个名为array的公开访问者,你可以说IScalarOperators<T> result = matrix.array[0, 0].Add(matrix.array[0, 1]);并获得将两者加在一起的表示。然后,您可以对此执行任何进一步的操作,依此类推。