c#通用处理器

本文关键字:处理器 | 更新日期: 2023-09-27 18:10:09

我有一个问题,它需要一个标准的输入组合,但是有几个算法('处理器')可以解决它。输出是一个布尔值。每个处理器只对一个特定场景有效,并且永远不会有多个处理器是有效的。

每个处理器通过向它提供一些初始输入来确定它是否有效。如果它是有效的,那么它就会根据这些初始输入计算一些信息,并存储这些信息——因为这些信息在最终的过程中是有用的。然后,如果它有效,则向处理器提供额外的输入,并返回输出。

如果没有处理器有效,则给出默认答案。

算法在伪代码中是这样的:

process(inputs) 
   for each processor
      determine validity and get data
      if valid
         use data to output result
      end if
   end for
  output default result
end

下面是一个c#示例,它在语法上是无效的。这只是一个例子,在现实生活中,输入比字符串和整数更复杂。第二个输入的计算(在人为的例子中是int i)在循环中重复执行,而第一个输入只计算一次——因此进程是否有效与处理器的结果是分离的。作为使用IEnumerable的替代方法,可以使用处理器数组或列表。

   public class ProcessController
   {
      public static IEnumerable<Processor<X>> GetProcessors<X>() where X: ProcessorInfo
      {
         yield return new ProcessorA();
         yield return new ProcessorB();
      }
      public static bool Process<X>(String s, int i) where X : ProcessorInfo
      {
         foreach (Processor<X> processor in GetProcessors<X>())
         {
            X x = (X) processor.GetInfoIfCanProcess(s);
            if (x != null)
            {
               return processor.GetResult(x, i);
            }
         }
         return false;
      }
   }
   public abstract class Processor<T> where T: ProcessorInfo
   {
      public abstract T GetInfoIfCanProcess(String s);
      public abstract bool GetResult(T info, int i);
   }
   public interface ProcessorInfo
   {
      bool IsValid();
   }
   public class ProcessorA: Processor<ProcessorA.ProcessorInfoA>
   {
      public class ProcessorInfoA: ProcessorInfo
      {
         public bool IsValid()
         {
            //do something!
         }
      }
      public override ProcessorInfoA GetInfoIfCanProcess(string s)
      {
         //do something!
      }
      public override bool GetResult(ProcessorInfoA info, int i)
      {
         //do something!
      }
   }
   public class ProcessorB : Processor<ProcessorB.ProcessorInfoB>
   {
      public class ProcessorInfoB : ProcessorInfo
      {
         public bool IsValid()
         {
            //do something!
         }
      }
      public override ProcessorInfoB GetInfoIfCanProcess(string s)
      {
         //do something!
      }
      public override bool GetResult(ProcessorInfoB info, int i)
      {
         //do something!
      }
   }

我在GetProcessors方法中得到语法错误:不能隐式地将类型Play.ProcessorA转换为Play.Processor<X>。我怎么才能避开这个问题呢?

c#通用处理器

您正在尝试使用泛型来耦合处理器类和它的处理器信息类,这是有问题的。您最终会得到一个松散耦合,您只是将对象强制转换为它们应该是什么,而不是使泛型确保类型是正确的。

我建议您通过在类本身中存储信息来避免这个问题。运行处理器的代码不需要知道处理器使用的信息,它只需要知道处理器是否有效。

返回一个布尔值而不是一个ProcessorInfo对象,并将相关数据保存在Processor对象中。如果处理器是有效的,则它拥有所需的数据。如果没有,当您继续尝试下一个处理器时,它将与从第一步获得的数据一起消失。

解决这个问题最简单的方法是使用OfType:

private static IEnumerable<object> GetProcessors()
{
    yield return new ProcessorA();
    yield return new ProcessorB();
}
public static IEnumerable<Processor<X>> GetProcessors<X>() where X: ProcessorInfo
{
    return GetProcessors.OfType<Processor<X>>();
}

由于Processor<X>是不变的,因此没有可以使用的通用类型,并且由于X是在方法之外选择的,因此需要使用动态类型检查。