C# 从抽象类将枚举作为参数传递
我有一个抽象基类,C# 从抽象类将枚举作为参数传递,c#,enums,C#,Enums,我有一个抽象基类,TestFactory,它看起来像: public abstract class TestFactory { //static method that can create concrete factories public static TestFactory CreateTestFactory(FactoryType factoryType) { TestFactory factory
TestFactory
,它看起来像:
public abstract class TestFactory
{
//static method that can create concrete factories
public static TestFactory CreateTestFactory(FactoryType factoryType)
{
TestFactory factory = null;
switch (factoryType)
{
case FactoryType.Blood:
factory = new BloodTestFactory();
break;
case FactoryType.Urine:
factory = new UrineTestFactory();
break;
default:
break;
}
return factory;
}
//BloodTestFactory and UrineTestFactory are concrete types
//that will need to create their own tests
//this enum parameter needs to 'switch' between
//BloodTestType and UrineTestType
public abstract LabTest CreateTest(Enum e);
}
public enum FactoryType
{
Blood,Urine
}
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
所以这个类创建了一个具体的工厂,比如:
public class BloodTestFactory :TestFactory
{
//both BloodTestFactory and UrineTestFactory will create a LabTest object
//I would like to have a BloodTestType and UrineTestType enum, what do I need
//to do to pass a generic Enum as a parameter and then switch on BloodTestType
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
//switch (e)
//{
// default:
// break;
//}
//creation logic here
}
}
public enum BloodTestType
{
H1AC,Glucose
}
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
BloodTest
本身是一个抽象类,它将基于枚举值返回一个具体的BloodTest
对象。为了清楚起见,我想要一个BloodTestType
和UrineTestType
(未显示)枚举。由于CreateTest
方法是抽象的,当我想创建BloodTest
s时,如何确保我能通过BloodTestType
,当我想创建UrineTest时通过UrineTestType
枚举?只需在重写方法中测试类型安全性即可:
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
我不确定这是否是满足此需求的最佳方法,我将把设计模式讨论留给评论/其他答案
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
我不一定要这样做,但是,为了使您的代码正常工作,我会在TestFactory
上为enum
引入一个类级通用参数
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
public abstract class TestFactory<TTestType>
{
public abstract LabTest CreateTest(TTestType testType);
}
就我个人而言,我可能会将这两个工厂分解成没有基的独立类,或者考虑使用接口。在“常用”方法中处理特定参数是很困难的。只需在基类中添加参数检查:
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
public abstract class TestFactory
{
//static method that can create concrete factories
public static TestFactory CreateTestFactory(FactoryType factoryType)
{
if (!Enum.IsDefined(typeof(FactoryType), factoryType)
{
throw InvalidEnumArgumentException(...);
}
TestFactory factory = null;
switch (factoryType)
{
case FactoryType.Blood:
factory = new BloodTestFactory();
break;
case FactoryType.Urine:
factory = new UrineTestFactory();
break;
default:
break;
}
return factory;
}
//...
}
有一种很好的方法可以做到这一点,它会产生如下代码:
public override LabTest CreateTest(Enum e)
{
BloodTest bt = null;
if(!e.GetType.Equals(typeof(BloodTestType)))
{
// throw type exception of your choice
}
}
var client = new LabTestClient();
client.Run<BloodTestFactory,BloodTestType>(BloodTestType.H1AC);
client.Run<BloodTestFactory,BloodTestType>(BloodTestType.Glucose);
// outputs
// BloodTest: H1AC
// BloodTest: Glucose
你能不能在
CreateTest
方法中把你的泛型Enum e
转换成具体的BloodTestType
。我只是好奇是否有更“优雅”的方式来做这件事。我知道枚举不做继承,但我想可能有办法解决这个问题。你可能不知道,但实际上,最后一个可能需要的枚举可能相当大。我越看这个问题,就越觉得你的架构是错误的。您试图在枚举上进行切换,以确定要执行哪种测试,但像工厂方法/抽象工厂这样的模式的全部要点是从代码中删除这种分支逻辑。因此,您将得到类GlucoseBloodLabTest
,H1ACBloodLabTest
,SomeUrineLabTest
等。所有这些都是从基类LabTest
继承的。如果你想知道如何改变你的代码以另一种方式完成它,请发到这里,我将为你准备一个单独的答案。@Jamiec我相信我没有很好地解释它,但在我的设计中,我也有了血液测试
。因此,抽象工厂创建工厂,而血液测试工厂可以创建几种抽象血液测试类型中的任意一种。不过,我确实同意,我的设计似乎并不理想。@Jamiec我一直处于知识搜索模式,我非常感谢任何知识会议:)这种工作,除了CreateTestFactory
方法现在也需要采用泛型,否定使用FactoryType
@Jamiec是的,该方法需要返回一个TestFactory
,就像您所说的,这会使方法变得毫无意义。@wootscootinboogie真的不确定。我现在会回顾一下基类的必要性。您希望由基类公开的方法必须采用派生类特定的参数,这在我看来是不必要的。@AdamHouldsworth我倾向于同意您的看法。:)@Jamiec我总是发现很难找到一种处理逻辑相关实体的通用方法,但碰巧需要特定于实体的方法参数(如本例所示)。你对它的方法有什么想法?老实说,这有点超出我的工资等级!:)非常感谢有机会学习。您能解释一下where-TFactory:LabTestFactory,new()
部分吗?where-TFactory:LabTestFactory,new()
-a指示泛型类型必须继承LabTestFactory
,并且必须具有无参数构造函数(允许类型本身的行为类似于工厂-请参见方法中的new-TFactory()
)