如何确定对象的类型并将其作为参数传递给方法?

时间:2014-09-18 08:09:40

标签: c# oop

我的应用程序包含一个名为Statistic的基类和三个继承自它的类:LSPCPUMemory。我还有一个名为ExecuteRequest的附加类,其构造函数采用Statistic的实例或其中一个派生类型(LSPCPUMemory) 。我想要做的是:确定它是什么类型的对象(LSPCPU还是Memory)。

为了实现这一点,我创建了DeterminateKpiType方法,该方法将检查传入的Statistic实例并将其强制转换为该类型的特定属性。完成后,此特定对象将传递给RunRequest()方法。不幸的是,我在尝试解决此问题时遇到了问题。

我收到错误(调用DeterminateKpiType()时),说它无法返回这些类型,我也不知道如何将对象传递给RunRequest()方法。我怎样才能达到这个效果?如果事情不清楚,请随时回复/询问。

以下是代码清单:

class ExecuteRequest
{
    public Statistic KPI { get; set; }
    public LSP LSP { get; set; }
    public CPU CPU { get; set; }
    public Memory Memory { get; set; }

    public ExecuteRequest(Statistic kpi)
    {
        KPI = kpi;
        specificStatisticKPI = DeterminateKpiType(KPI);
        RunRequest(specificStatisticKPI)
    }

    public T DeterminateKpiType<T>(Statistic KPI)
    {
        if (KPI.GetType() == typeof(LSP))
        {
            LSP = KPI as LSP;
            return LSP;
        }

        if (KPI.GetType() == typeof(CPU))
        {
            CPU = KPI as CPU;
            return CPU;
        }

        if (KPI.GetType() == typeof(Memory))
        {
            Memory = KPI as Memory;
            return Memory;
        }

    }

    public void RunRequest(specificStatisticKPI what type ?????)
    {
        specificStatisticKPI.SomeMethod
    }
}

2 个答案:

答案 0 :(得分:0)

我有一些理论我不会,如果它会有所帮助,但我很乐意告诉你,首先specificStatisticKPI它是什么类型的?如果设置为Statistic类型我认为您需要转换它,或者它不能包含MemoryLSPCPU,那么其次是RunRequest()方法应该能够采用三种类型,或者如果处理这些事情,这些类可以隐式地相互转换,我相信你的代码应该可以工作。 祝你好运

答案 1 :(得分:0)

您采取的方法存在一些挑战(我怀疑这些会导致您面临的一些混乱)所以我将尝试概述这些并提供应该给出的解决方案你想要的结果。

挑战1:

你在ExecuteRequest课程的构造函数中做了太多逻辑。构造函数应限于极其简单的条件检查(如果有的话),并且肯定不会执行任何操作。在这里你至少有两个选择:

  1. 将您的ExecuteRequest类重构为没有构造函数的静态类(我没有看到基于您当前代码的原因使其成为可实例化的类型)和一个接受{的静态方法{1}}实例作为参数(例如,您的Statistic方法)。
  2. 将构造函数更改为仅初始化RunRequest实例,并使使用Statistic的代码调用RunRequest。
  3. 关于构造函数的特别注意事项(取自下面的MSDN链接):

      

    ......使用公共字段不是推荐的编程习惯   因为它允许程序中任何地方的任何方法不受限制   未经验证的访问对象的内部工作。数据成员应该   通常是私人的,只能通过课堂访问   方法和属性。

      

    在构造函数中执行最少的工作。构造者不应该做太多   除了捕获构造函数参数之外的工作。任何费用   其他处理应延迟到需要。

    以下是构造函数的一些有用指南以及如何最好地使用它们:

    挑战2:

    使用泛型和条件类型逻辑通常互斥(其中一个选项优先于另一个选项),并且将两者结合起来通常是Code Smell。使用泛型时,其中一个好处来自于使用“泛型”约束&#39;。这些约束允许您尽可能多地了解基类型的所有潜在传入实现,同时允许创建新实例而无需修改代码。这个想法基本上是Liskov Substitution之一。

    有关泛型类型约束的详细信息,请参阅:http://msdn.microsoft.com/en-us/library/d5x73970.aspx

    以下是MSDN文档的摘录:

      

    通过约束类型参数,可以增加数量   允许的操作和方法调用   约束类型和其继承层次结构中的所有类型。   因此,当您设计泛型类或方法时,如果您将   对简单的泛型成员执行任何操作   您可以分配或调用System.Object不支持的任何方法   必须将约束应用于类型参数。


    可能的解决方案

    总有很多方法可以解决这样的编程问题,这里有两个版本可以解决您所面临的挑战。

    注意:我在LinqPad中创建了这些内容,因此它们都经过测试工作(但您的实际课程可能与我的不同)。

    变体1(具有类范围泛型类型约束的可实例化ExecuteRequest):

    ExecuteRequest

    <强>输出:

      

    这是SomeMethod的CPU实现。

         

    这是SomeMethod的LSP实现。

         

    这是SomeMethod的Memory实现。

    变体2(具有泛型类型参数和约束的静态void Main() { LSP lspStatistic = new LSP(); Memory memoryStatistic = new Memory(); CPU cpuStatistic = new CPU(); ExecuteRequest<CPU> cpuRequest = new ExecuteRequest<CPU>(cpuStatistic); ExecuteRequest<LSP> lspRequest = new ExecuteRequest<LSP>(lspStatistic); ExecuteRequest<Memory> memoryRequest = new ExecuteRequest<Memory>(memoryStatistic); cpuRequest.RunRequest(); lspRequest.RunRequest(); memoryRequest.RunRequest(); } public class ExecuteRequest<TStatistic> where TStatistic : Statistic { private TStatistic _kpi; //Whichever type the class was created as. This enables us to have intellisense support for the specific generic type outside of this class if we need it. //Hide the default constructor from the outside world (require a statistic) private ExecuteRequest() : this(null) { } // end default constructor public ExecuteRequest(TStatistic kpi) { _kpi = kpi; } // end overloaded constructor public void RunRequest() { this.KPI.SomeMethod(); //Since we know that KPI will be AT LEAST a Statistic as specified by the generic type constraint, we can access the base class members here without having to figure out which type it is because we don't actually care what type it is, just that it is a Statistic } // end method RunRequest public TStatistic KPI { get { return _kpi; } set { _kpi = value; } } // end property KPI } // end class ExecuteRequest public abstract class Statistic { protected Statistic() { } // end default constructor public abstract void SomeMethod(); } // end class Statistic public class LSP : Statistic { public LSP() : base() { } // end default constructor public override void SomeMethod() { Debug.WriteLine("This is the LSP implementation of SomeMethod."); } // end method SomeMethod } // end class LSP public class CPU : Statistic { public CPU() : base() { } // end default constructor public override void SomeMethod() { Debug.WriteLine("This is the CPU implementation of SomeMethod."); } // end method SomeMethod } // end class CPU public class Memory : Statistic { public Memory() : base() { } // end default constructor public override void SomeMethod() { Debug.WriteLine("This is the Memory implementation of SomeMethod."); } // end method SomeMethod } // end class Memory ):

    ExecuteRequest

    <强>输出:

      

    这是SomeMethod的LSP实现。

         

    这是SomeMethod的Memory实现。

         

    这是SomeMethod的CPU实现。

    作为替代方案,由于静态实现你不需要智能感知,你可以像所以一样省略通用:

    void Main() {
        LSP lspStatistic = new LSP();
        Memory memoryStatistic = new Memory();
        CPU cpuStatistic = new CPU();
    
        ExecuteRequest.RunRequest<LSP>(lspStatistic);
        ExecuteRequest.RunRequest<Memory>(memoryStatistic);
        ExecuteRequest.RunRequest<CPU>(cpuStatistic);
    }
    
    public static class ExecuteRequest {
    
        public static void RunRequest<TStatistic>(TStatistic statInstance) where TStatistic : Statistic {
            if(statInstance != null) {
                statInstance.SomeMethod();
            } // end if
        } // end method RunRequest
    
    } // end class ExecuteRequest
    

    希望这能为你提供一些如何前进的指导。