在处理Web请求时使用SOLID方法

时间:2017-04-12 13:39:18

标签: c# solid-principles

我目前正在开发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);
}

2 个答案:

答案 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;不要无缘无故地依赖彼此。