我目前正在开发Service Fabric解决方案,其中数据从一个服务发送到下一个服务。
我发送了几个属性的类。这个类是一种datatransfer对象。我想使用一种可靠的方法来防止使用导致切换逻辑的整数。
即。我不想要这个:
public void ExecuteFunctionForType(IntegerTypedClass myClass, IInterface myinterface)
{
switch(myClass.typeInt)
{
case 1:
// Do shizzle for type 1
myinterface.execute1();
break;
case 2:
// do shizzle for type 2
myinterface.execute2();
break;
}
}
相反,我想实现一种SOLID方法。想到的那个如下所示:
public abstract class AbstractTypedClass
{
public abstract void ExecuteInheritedFunction(IInterface myinterface);
}
public class FirstTypedClass : AbstractTypedClass
{
public override void ExecuteInheritedFunction(IInterface myinterface)
{
// do shizzle for the first typed class
myinterface.execute1();
}
}
public class SecondTypedClass : AbstractTypedClass
{
public override void ExecuteInheritedFunction(IInterface myinterface)
{
// do shizzle for the second typed class
myinterface.execute2();
}
}
这种方法存在的问题是AbstractTypedClass
及其所有孩子都会依赖IInterface
,这是我不想要的。这是因为它是一个服务结构接口,它带来了许多其他依赖性。
我更愿意有一个解决方案,你可以使用坚实的原则,而不是创建一个依赖于不同的库,这将混乱我的解决方案
我无法使用的东西:
部分类,因为它们需要在同一个组合中
扩展方法,因为默认方法被调用:
public static class TypedClassExtensions
{
public static void executeExtension(this AbstractTypedClass request, IInterface myinterface)
{
throw new NotImplementedException();
}
public static void executeExtension(this FirstTypedClass request, IInterface myinterface)
{
myinterface.execute1();
}
}
// when calling the code like so, the not implemented exception is thrown:
public void execute(AbstractTypedClass myclass, IInterface myinterface)
{
myclass.executeExtension(myinterface);
}
答案 0 :(得分:1)
在C#7中,您可以使用模式匹配来避免使用策略或访问者模式。这样可以生成更清晰的代码,因为您不必将相同的方法添加到所有具体类中,或者使用双重调度。
void ExecuteFunctionForType(AbstractTypedClass myClass, IInterface myinterface)
{
switch(myClass)
{
case FirstTypedClass it1:
// Do shizzle for type 1
myinterface.execute1(it1.Prop1);
break;
case SecondTypedClass it2:
// do shizzle for type 2
myinterface.execute2(it2.Prop2);
break;
}
}
假设接口和实现如下所示:
interface IInterface {void execute1(string input);void execute2(int input);}
class SomeClass:IInterface
{
public void execute1(string input) => Console.WriteLine($"1 {input}");
public void execute2(int input) => Console.WriteLine($"2 {input}");
}
和这样的类:
public abstract class AbstractTypedClass{ }
public class FirstTypedClass : AbstractTypedClass
{
public string Prop1 =>"First";
}
public class SecondTypedClass : AbstractTypedClass
{
public int Prop2 =>500;
}
您可以使用switch语句为每种类型调用不同的方法,该语句在类型上执行模式匹配。以下代码:
var it=new SomeClass();
ExecuteFunctionForType(new FirstTypedClass(),it);
ExecuteFunctionForType(new SecondTypedClass(),it);
将产生:
1 First
2 500
类型上的模式匹配返回匹配类型的强类型变量。可以使用每种具体类型的成员,而无需在接口或抽象类上进行定义。
答案 1 :(得分:0)
使用SOLID原则我认为您的方法看起来像这样:
依赖性反转原则建议您仅依赖于函数所需的接口。所以在你的抽象类中,我会简单地使它成为通用的,并在抽象类的实现中定义依赖项。这样,如果您可以在不同的程序集中实现不同的版本,那些程序集就不会有不必要的依赖。
// ------------ Assembly A -----------------
public abstract class AbstractTypedClass<T>
{
public abstract void ExecuteInheritedFunction(T obj);
}
// ------------ Assembly B -----------------
IHugeDependency
{
void execute1();
...more
}
public class FirstTypedClass : AbstractTypedClass<IHugeDependency>
{
public override void ExecuteInheritedFunction(IHugeDependency obj)
{
// do shizzle for the first typed class
obj.execute1();
}
}
// ------------ Assembly C -----------------
ISmallerDependency
{
void execute2();
}
public class SecondTypedClass : AbstractTypedClass<ISmallerDependency>
{
public override void ExecuteInheritedFunction(ISmallerDependency obj)
{
// do shizzle for the second typed class
obj.execute2();
}
}
使用这种方法组件B和C都依赖于A但B&amp;不要无缘无故地依赖彼此。