创建一个泛型类型的成员变量,而不在类上指定类型参数

时间:2011-09-01 15:28:47

标签: c# generics

我为不清楚的标题道歉,我真的不知道怎么说。我将用代码演示。

public class CalculationService
{
    private static Calculator<StaticInstrument, StaticResult> _staticCalculator;
    private static Calculator<DynamicInstrument, DynamicResult> _dynamicCalculator;
    private static readonly object IsInitializedLock = new object();

    public byte[] ProcessStatic()
    {
        lock (IsInitializedLock)
        {
            _staticCalculator = new Calculator<StaticInstrument, StaticResult>();
        }

        return _staticCalculator.Calculate();
    }

    public byte[] ProcessDynamic()
    {
        lock (IsInitializedLock)
        {
            _dynamicCalculator = new Calculator<DynamicInstrument, DynamicResult>();
        }

        return _dynamicCalculator.Calculate();
    }
}

除了Calculator对象的类型参数不同之外,我有许多相同的方法。

问题是,因为CalculationService是WCF服务,所以不能具有任何类型参数。出于这个原因,我不能简单地创建静态成员Calculator<TInstrument, TResult>,因为我无法将类型参数放在CalculationService上。

我的理想解决方案将是这样的:

public class CalculationService
{
    private static Calculator<TInstrument, TResult> _calculator;
    private static readonly object IsInitializedLock = new object();

    public byte[] Process<TInstrument, TResult>()
    {
        lock (IsInitializedLock)
        {
            _calculator = new Calculator<TInstrument, TResult>();
        }

        return _calculator.Calculate();
    }

    public byte[] ProcessStatic()
    {
        return Process<StaticInstrument, StaticResult>();
    }

    public byte[] ProcessDynamic()
    {
        return Process<DynamicInstrument, DynamicResult>();
    }
}

但我无法在private static Calculator<TInstrument, TResult> _calculator上指定类型信息而无法创建CalculationService成员,而我无法对WCF执行此操作。

我能想到的唯一方法就是

private static dynamic _calculator;

还有其他方法吗?如果可能的话,我宁愿避免使用动态,我不确定性能影响是什么,如果有的话。

3 个答案:

答案 0 :(得分:1)

我认为我不理解您之后关于在我的CalculationService类中“只有一个计算器实例”的评论。相反,在我看来,每个&lt; TInstrument,TResult&gt;需要一个实例,就像你最初发布的代码一样。我认为下面的代码会做你想要的(有了额外的好处,静态初始化规则将在适当的时候线程安全地构造计算器)。

public class CalculationService {
  private static class Inner<TInstrument, TResult> {
    public static readonly Calculator<TInstrument, TResult> _calculator;

    static Inner() {
      _calculator=new Calculator<TInstrument, TResult>();
    }
  }

 public byte[] ProcessStatic() {
    return Inner<StaticInstrument, StaticResult>._calculator.Calculate();
  }

  public byte[] ProcessDynamic() {
    return Inner<DynamicInstrument, DynamicResult>._calculator.Calculate();
  }
}

答案 1 :(得分:0)

您可以使用继承“烧入”类型以防止WCF抱怨。

public class StaticCalculator:Calculator<StaticInstrument, StaticResult> {}
public class DynamicCalculator:Calculator<DynamicInstrument, DynamicResult> {}

public class CalculationService
{
    private static StaticCalculator _staticCalculator;
    private static DynamicCalculator _dynamicCalculator;
    ...

我之前已经完成了这项工作,以解决WCF缺乏对泛型类型参数的支持。

答案 2 :(得分:0)

如果您只想要1个版本的服务,则不能拥有一个_calculator变量。 “简单”的方法是使用某种版本的查找结构(如字典等)并查找正确的计算器。使用TInstrumentTResult的组合作为计算器的关键。

然后,您可以使用typeof运算符来获取密钥。类似的东西:

_calculators = new Dictionary<Type,<Dictionary<Type,Calculator<TInstrument, TResult>>>();
...
var key1 = typeof(TInstrument);
var key2 = typeof(TResult);
var calculator = _calculators[key1].[key2];
...

我知道这可能看起来很复杂,因为用于创建计算器词典的通用词典的泛型语法......但它确实有效。

希望这有帮助,

埃里克。