【问题标题】:Creating a generic typed member variable without type parameters specified on the class创建一个没有在类上指定类型参数的泛型类型成员变量
【发布时间】:2011-09-01 15:28:47
【问题描述】:

对不起,标题不清楚,我真的不知道该怎么说。我将用代码进行演示。

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();
    }
}

我有很多方法是相同的,除了计算器对象的类型参数不同。

问题是,因为CalculationService 是一个WCF 服务,它不能有任何类型参数。由于这个原因,我不能简单地创建一个静态成员Calculator&lt;TInstrument, TResult&gt;,因为我不能在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>();
    }
}

但如果不指定 CalculationService 的类型信息,我无法创建 private static Calculator&lt;TInstrument, TResult&gt; _calculator 成员,而 WCF 无法做到这一点。

我能想到的唯一方法就是拥有

private static dynamic _calculator;

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

【问题讨论】:

标签: c# generics


【解决方案1】:

我不认为我理解您后来关于“在我的 CalculationService 类上只有 一个 Calculator 实例”的评论;相反,在我看来,每个 都需要一个实例,就像您最初发布的代码一样。我认为下面的代码会做你想做的事(静态初始化规则将在正确的时间线程安全地构造计算器)。

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();
  }
}

【讨论】:

    【解决方案2】:

    您可以使用继承“烧入”类型以防止 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 缺乏对泛型类型参数的支持。

    【讨论】:

    • 不,问题是我只想在我的 CalculationService 类上有 一个 Calculator 实例。具体的泛型类型工作正常。
    【解决方案3】:

    如果您只需要 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];
    ...
    

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

    希望这会有所帮助,

    埃里克。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      相关资源
      最近更新 更多