动态设置对方法中使用的变量的引用

Dynamically setting the reference to a variable used in a method

我不确定这个标题是否正确。无论如何,我有一个 class,它有许多控制立体声的方法。每种方法都会向串行端口发送一条命令。支持多种型号的立体声,每个立体声可能需要发送不同的命令。 例如model_A可能需要发送命令"VOLUP"到串口,"model_B"可能需要发送命令"GAINUP"增加音量。我想要一种名为 IncreaseVolume 的方法,如下所示:

 public void IncreaseVolume()
 {
     serialPort.WriteLine(volumeCommand);
 }

此方法将在设置收音机型号后从另一个class调用。现在对于两个收音机我可以这样做:

public class StereoControl
{
    string volumeCommand;
    string model_A_Volume_Command = "VOLUP";
    string model_B_VOlume_Command = "GAINUP";

    public void Set_Radio_Model(string model)
    {
        if (model == "modelA")
        {
            volumeCommand = model_A_Volume_Command;
        }

        else if (model == "modelB")
        {
            volumeCommand = model_B_Volume_Command;
        }
     }

     public void IncreaseVolume(volumeCommand)
     {
         serialPort.WriteLine(volumeCommand);
     }
}

所以主程序首先会设置模型,然后只要音量需要增加,它就会调用 IncreaseVolume 方法。 问题是可能有几十个立体声和几十个命令,我不一定要在 if then 或 case 语句中包含所有这些。 我考虑过为每个包含命令的模型创建结构,但是您如何 select 在方法中使用哪个结构? 我相信有一种更优雅的方法可以做到这一点,并且愿意接受建议。

第一个答案虽然可用,但当我们得到 100 多个命令和 200 多个立体声时,它会有点难以处理。所以这是另一种可能性,但我不知道如何在整个应用程序中获得可用的 class 引用。

public Class Model_A
{
    string volumeCommand = "VOLUP";
}

public Class Model_B
{
    string volumeCommand = "GAINUP";
}

public Class StereoControl
{
    public void Set_Radio_Model(String model)
    {
        if (model == "model_a")
        {
             var _radio = new Model_A();
        }

         else if (model == "model_b")
        {
             var _radio = new Model_B();
        }
    }

    public void IncreaseVolume()
    {
        serialPort.WriteLine(_radio.volumeCommand);
    }
}

当然这里的问题是_radio的范围只在Set_Radio_Model范围内。有没有办法让 _radio 在任何地方都可用? 汤姆

最基本的方法是拥有立体声名称的枚举,然后在 OOP 中实现它 (希望大家帮忙改进)这个就看我的意见了

1- 定义 enum 如:

public enum StereoBrand
{
    Stero1 = 0,
    Stereo2 = 1
}

2- 定义一个接口来强制执行所有立体声实现 IncreaseVolume() 如:

public interface IStereo
{
    string VolumeCommand { get; }
    string SteroeName { get; }
    void IncreaseVolume();
}

通过上面的界面,每个立体声音响都应该有一个名字StereoName

3- 然后像这样实现 StereoController :

public class SteroController : IStereo
{
    public virtual string SteroeName
    {
        get
        {
            return string.Empty;
        }
    }

    public virtual string VolumeCommand
    {
        get
        {
            return string.Empty;
        }
    }
    public virtual void IncreaseVolume()
    {
        throw new NotImplementedException();
    }
    public static SteroController GenerateStereo(StereoBrand brand)
    {
        SteroController stereo = null;
        switch (brand)
        {
            case StereoBrand.Stero1:
                stereo = new Stereo1();
                break;
            case StereoBrand.Stereo2:
                stereo = new Stereo2();
                break;
        }
        return stereo;
    } 
}

步骤 3 的注释:

3.1- StereoController 实现 IStereo 并将 prop 和 Increase 方法更改为 Virtual,所有 Stereo 都可以覆盖它们。

3.2- GenerateStereo 通过其 StereoName

创建相关的立体声

4- 假设我们必须在此处 Stereo1Stereo2 实现立体声 类,例如:

public class Stereo1 : SteroController
{
    public override string SteroeName
    {
        get
        {
            return "Streo1";
        }
    }

    public override string VolumeCommand
    {
        get
        {
            return "Command1";
        }
    }

    public override void IncreaseVolume()
    {
        //Do anything with VolumCommand
    }
    public Stereo1()
    {

    }
}
public class Stereo2 : SteroController
{
    public override string SteroeName
    {
        get
        {
            return "Streo2";
        }
    }

    public override string VolumeCommand
    {
        get
        {
            return "Command2";
        }
    }

    public override void IncreaseVolume()
    {
        //Do anything with VolumCommand2
    }
    public Stereo2()
    {

    }
}

5- 最后一步是像这样使用它们:

var stero = SteroController.GenerateStereo((StereoBrand)Enum.Parse(typeof(StereoBrand), "brandName"));
stero.IncreaseVolume();

备注:

N1: 这个比较好用反射实现GenerateStereo 就是把所有的IStereo都找出来然后用反射创建一个实例

N2:避免 switch-case 的另一种解决方案是使用反射来查找相关的 Stereo,例如:

public static SteroController GenerateStereo(StereoBrand brand)
{
    SteroController stereo = null;
    var type = typeof(IStereo);
    var types = AppDomain.CurrentDomain.GetAssemblies()//Find all classes which implemented ISereo
        .SelectMany(s => s.GetTypes())
        .Where(p => type.IsAssignableFrom(p)).ToList();
    foreach(Type t in types)
    {
        var stereoNameProp = t.GetProperties().SingleOrDefault(p => p.Name == "StereoName");//Get stereo name prop
        if (stereoNameProp != null && stereoNameProp.GetValue(t).ToString() == brand.ToString())//Check it with brand name
            stereo =(SteroController)Activator.CreateInstance(type);//Make an instance
    }  
    return stereo;
}

希望对你有所帮助,给你线索。