有没有合适的设计模式来重构这个C#代码

M.H*_*san 1 .net c# generics refactoring design-patterns

我有2个不同的第三方程序集,它们为业务服务提供相同的API并使用相同的类名(~40个类/类型/扩展名)但位于不同的程序集中:

    Company.Assemply.V1
    Company.Assemply.V2
Run Code Online (Sandbox Code Playgroud)

我引用了项目中的两个程序集.

这些程序集没有通用接口,第三方也无法提供通用接口

因此,c#编译器将两个程序集中的每个类型视为不同的类型.

我想Myservice 为每个程序集实现一个类来支持V1/V2版本.

我使用以下代码来实现 Myservice.V1.Myclass

    //#define V1

    #if V1
       using  Company.Assemply.V1;
    #else
       using  Company.Assemply.V2;
    #endif

    #if V1
      namespace Myservice.V1
    #else
      namespace Myservice.V2
    #endif
    {
       //my implementation that use all classes /types in any v1/v2 assembly
        class MyClass {.... }
     }
Run Code Online (Sandbox Code Playgroud)

然后我将相同的代码复制并粘贴到其他c#文件 MyClassV2.cs (大约400行)中,以获取 Myservice.V2.Myclass和取消注释编译器标志#define V1

我不能使用泛型

        MyClass  <T> where T:??
Run Code Online (Sandbox Code Playgroud)

因为T没有通用接口

这两个班级工作正常.

问题是在维护v1时,我必须将代码复制/粘贴到另一个文件中,MyClassV2.cs并取消注释编译器标志#define V1以支持V2.

是否有更好的方法/合适的设计模式/重构技术可以解决这样的问题.我想使用/维护一个代码库,避免复制/粘贴其他类版本.

给我一个重构上面代码的例子.

Nig*_*888 5

一种选择是使用适配器模式,这是向BCL添加抽象的常用方法,以及不使用它们的第三方代码.例如,你必须在指定的第三方组件的类型MyClass和双方V1V2共享相同的成员:

public interface IMyClass
{
    // All members of MyClass 
    // (except we have a special case for DoSomething() because it
    // has a return type SomeType we also need to adapt to ISomeType).

    ISomeType DoSomething();
}

public class MyClassV1 : V1.MyClass, IMyClass
{
    // No need to re-implement members (base class satisfies interface)
    // However, if there are return parameters, you will need to 
    // also use a decorator pattern to wrap them in another adapter.

    public override ISomeType DoSomething()
    {
        return new SomeTypeV1(base.DoSomething());
    }

}

public class MyClassV2 : V2.MyClass, IMyClass
{
}

public interface ISomeType
{
     // All members of SomeType
}

public class SomeTypeV1 : ISomeType
{
    private readonly SomeType someType;

    public SomeType(SomeType someType)
    {
        this.someType = someType;
    }

    // re-implement all members and cascade the call to someType
}
Run Code Online (Sandbox Code Playgroud)

然后您可以IMyClass在您的应用程序中使用,使用DI注入您需要的任何一个.

public class HomeController : Controller
{
    private readonly IMyClass myClass;

    public HomeController(IMyClass myClass)
    {
        this.myClass = myClass
    }
}
Run Code Online (Sandbox Code Playgroud)

如果需要在运行时在实现之间切换,请考虑策略模式.