C# 根据C中具有无限组合的两个参数定义要使用的函数#
我有一个问题必须通过一个我不知道的设计模式来解决。这适用于不同坐标系之间的变换。我向你解释 1/我有一个引用系统集合(EPSG)的枚举: 这些枚举允许定义对象坐标使用的系统C# 根据C中具有无限组合的两个参数定义要使用的函数#,c#,generics,enums,coordinate-transformation,C#,Generics,Enums,Coordinate Transformation,我有一个问题必须通过一个我不知道的设计模式来解决。这适用于不同坐标系之间的变换。我向你解释 1/我有一个引用系统集合(EPSG)的枚举: 这些枚举允许定义对象坐标使用的系统 public struct Coordinate { public System system; public double X; public double Y; public double Z; } 可以有无限多个系统。枚举索引不一定相互跟随,也不能修改 2/对象必须能够从一个系统传递
public struct Coordinate
{
public System system;
public double X;
public double Y;
public double Z;
}
可以有无限多个系统。枚举索引不一定相互跟随,也不能修改
2/对象必须能够从一个系统传递到另一个系统。我将转换从一个系统应用到另一个系统。系统A->系统B。
此转换不会更改类型。它会更改坐标(x、y和z)的值,以便该点位于正确的位置,具体取决于其系统
所有的组合都是可能的。但是,根据起动系统的不同,更换系统的计算结果并不总是相同的
3/I有几个包含转换方法的静态类:
public static class WGS84
{
public static Coordinate ToNAD27 (double X, double Y, double Z)
{
...
}
public static Coordinate ToNAD83 (double X, double Y, double Z)
{
...
}
}
我们来解决这个问题
4/为了定义使用了哪种转换并避免大量的转换,如果我第一次使用一个开关,将包含起始系统和到达系统的对象作为参数:
public class SystemTransform
{
public System initial;
public System terminal;
}
public struct Coordinate
{
public System system;
public double X;
public double Y;
public double Z;
public Coordinate Transform (SystemTransform s)
{
switch(s)
{
case SystemTransform st when st.Initial == System.WGS84 && st.Terminal == System.NAD27:
return WGS84.ToNAD27(X, Y, Z);
...
case SystemTransform st when st.Initial == System.WGS84 && st.Terminal == System.Z:
throw new NotImplementedException ($ "{s} not implmented");
}
}
}
5/由于不切实际和美观,我转向一本字典:
public static class TransformWithDictionary
{
private static Dictionary <SystemTransform, Func <Coordinate , Coordinate >> ParserMap = new Dictionary <SystemTransform, Func <Coordinate , Coordinate >>
{
{new SystemTransform (System.WGS84, System.NAD27), coord => WGS84.ToNAD27(coord)},
{new SystemTransform (System.WGS84, System.NAD83), coord => WGS84.ToNAD83(coord)},
};
public MyObject GetParserFor (SystemTransform st, Coordinate coord)
{
if (! ParserMap.ContainsKey(st))
throw new NotImplementedException ("Unexpected file type value" + st);
return ParserMap[st](coord);
}
}
公共静态类TransformWithDictionary
{
私有静态字典ParserMap=新字典
{
{newsystemtransform(System.WGS84,System.NAD27),coord=>WGS84.ToNAD27(coord)},
{newsystemtransform(System.WGS84,System.NAD83),coord=>WGS84.ToNAD83(coord)},
};
公共MyObject GetParserFor(SystemTransform st,坐标坐标坐标)
{
如果(!ParserMap.ContainsKey(st))
抛出新的NotImplementedException(“意外的文件类型值”+st);
返回ParserMap[st](坐标);
}
}
有点优雅,但这并不能解决问题
从理论上讲,我面临着一个转变∞ 可能性。只需说,不可能手动填充并随时间进行维护
第三个想法是建一个工厂。但这并不能帮助我根据来源系统和到达系统定义使用哪个函数
知道吗解决这个问题的设计模式?我不确定我是否完全理解您的需求,但对我来说,简单的抽象就足够了
public abstract class CoordinateSystem
{
public double X {get; private set; }
public double Y {get; private set; }
public double Z {get; private set; }
protected CoordinateSystem( Double x, Double y, Double z )
{
X = x;
Y = y;
Z = z;
}
public abstract CoordinateSystemA ToA();
public abstract CoordinateSystemB ToB();
public abstract CoordinateSystemC ToC();
}
public class CoordinateSystemA : CoordinateSystem
{
public CoordinateSystemA( Double x, Double y, Double z )
: base(x, y, z )
{}
public override CoordinateSystemA ToA() {
return new CoordinateSystemA(X,Y,Z);
}
public override CoordinateSystemB ToB() {
return new CoordinateSystemB(2,2,2);
}
public override CoordinateSystemC ToC() {
return new CoordinateSystemC(3,3,3);
}
}
public class CoordinateSystemB : CoordinateSystem
{
public CoordinateSystemB( Double x, Double y, Double z )
: base(x, y, z )
{}
public override CoordinateSystemA ToA() {
return new CoordinateSystemA(1,1,1);
}
public override CoordinateSystemB ToB() {
return new CoordinateSystemB(X,Y,Z);
}
public override CoordinateSystemC ToC() {
return new CoordinateSystemC(3,3,3);
}
}
public class CoordinateSystemC : CoordinateSystem
{
public CoordinateSystemC( Double x, Double y, Double z )
: base(x, y, z )
{}
public override CoordinateSystemA ToA() {
return new CoordinateSystemA(1,1,1);
}
public override CoordinateSystemB ToB() {
return new CoordinateSystemB(2,2,2);
}
public override CoordinateSystemC ToC() {
return new CoordinateSystemC(X,Y,Z);
}
}
public static class Program {
public static void Main() {
CoordinateSystem coordinateSystem = new CoordinateSystemA(1,1,1);
CoordinateSystem b = coordinateSystem.ToB();
CoordinateSystem c = b.ToC();
}
}
通过放置ToX()在抽象类上,它强制所有继承坐标系(类)实现转换。然后,您可以在不了解系统的情况下在整个系统中使用抽象类,并轻松地转换为所需的系统
如果这不能满足您的要求,我认为您应该看看访问者模式。它有点复杂,但有很多例子。我不确定我是否完全理解您的需求,但对我来说,听起来简单的抽象就足够了
public abstract class CoordinateSystem
{
public double X {get; private set; }
public double Y {get; private set; }
public double Z {get; private set; }
protected CoordinateSystem( Double x, Double y, Double z )
{
X = x;
Y = y;
Z = z;
}
public abstract CoordinateSystemA ToA();
public abstract CoordinateSystemB ToB();
public abstract CoordinateSystemC ToC();
}
public class CoordinateSystemA : CoordinateSystem
{
public CoordinateSystemA( Double x, Double y, Double z )
: base(x, y, z )
{}
public override CoordinateSystemA ToA() {
return new CoordinateSystemA(X,Y,Z);
}
public override CoordinateSystemB ToB() {
return new CoordinateSystemB(2,2,2);
}
public override CoordinateSystemC ToC() {
return new CoordinateSystemC(3,3,3);
}
}
public class CoordinateSystemB : CoordinateSystem
{
public CoordinateSystemB( Double x, Double y, Double z )
: base(x, y, z )
{}
public override CoordinateSystemA ToA() {
return new CoordinateSystemA(1,1,1);
}
public override CoordinateSystemB ToB() {
return new CoordinateSystemB(X,Y,Z);
}
public override CoordinateSystemC ToC() {
return new CoordinateSystemC(3,3,3);
}
}
public class CoordinateSystemC : CoordinateSystem
{
public CoordinateSystemC( Double x, Double y, Double z )
: base(x, y, z )
{}
public override CoordinateSystemA ToA() {
return new CoordinateSystemA(1,1,1);
}
public override CoordinateSystemB ToB() {
return new CoordinateSystemB(2,2,2);
}
public override CoordinateSystemC ToC() {
return new CoordinateSystemC(X,Y,Z);
}
}
public static class Program {
public static void Main() {
CoordinateSystem coordinateSystem = new CoordinateSystemA(1,1,1);
CoordinateSystem b = coordinateSystem.ToB();
CoordinateSystem c = b.ToC();
}
}
通过放置ToX()在抽象类上,它强制所有继承坐标系(类)实现转换。然后,您可以在不了解系统的情况下在整个系统中使用抽象类,并轻松地转换为所需的系统
如果这不能满足您的要求,我认为您应该看看访问者模式。它有点复杂,但是有很多例子。似乎MyObject
是非常可变的,不是struct
的好候选者。case
语句似乎完全忽略了开关
vairables
。这真的有效吗?如果你有不同的转换,并且这些转换必须手工编码,那么我没有得到“具有无限可能性的开关”语句,你仍然必须编写无限转换,那么重点在哪里呢?在到系统结构b
,到系统结构x
等中你有什么类型的代码?如果它们真的都不同,那么你的问题本质上是复杂的。我能想到的唯一方法是将逻辑编码到数据文件中(或者不编码,但实际上是将其写入您将发明的DSL中)。这样,C代码只需要找到一个正确的文件,读取它,然后运行它。文件名可以以首字母
系统开头,以终端
系统结尾。虽然不清楚您最后想要实现什么,但您可能希望查看。如果您试图自动计算是否存在通过C1、C2、…CN类型将a转换为B的路径,那么您应该阅读图形上的路径查找。您还可以研究“度量单位”转换的实现……似乎MyObject
是非常可变的,对于struct
,它不是一个很好的候选者。case
语句似乎完全忽略了开关
VARABLEs
。这真的有效吗?如果你有不同的转换,并且这些转换必须手工编码,那么我没有得到“具有无限可能性的开关”语句,你仍然必须编写无限转换,那么重点在哪里呢?在到系统结构b
,到系统结构x
等中你有什么类型的代码?如果它们真的都不同,那么你的问题本质上是复杂的。我能想到的唯一方法是将逻辑编码到数据文件中(或者不编码,但实际上是将其写入您将发明的DSL中)。这样,C代码只需要找到一个正确的文件,读取它,然后运行它。文件名可以以首字母
系统开头,以终端
系统结尾。虽然不清楚您最后想要实现什么,但您可能希望查看。如果您试图自动计算是否存在将a转换为B的路径vi