动态设置对方法中使用的变量的引用
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- 假设我们必须在此处 Stereo1
和 Stereo2
实现立体声 类,例如:
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;
}
希望对你有所帮助,给你线索。
我不确定这个标题是否正确。无论如何,我有一个 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- 假设我们必须在此处 Stereo1
和 Stereo2
实现立体声 类,例如:
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;
}
希望对你有所帮助,给你线索。