代码之家  ›  专栏  ›  技术社区  ›  Daniel

引用未实例化/尚未存在的类

  •  0
  • Daniel  · 技术社区  · 8 年前

    我有一个Winforms应用程序,旨在与外部软件包集成。该应用程序从这些包中读取数据,并将其推送到我们的服务器,用户在那里登录并使用我们的应用程序(App)。

    public abstract ClassToImplement
    {
        public abstract void DefinedMethod1();
        public abstract void DefinedMethod2();
    }
    

    当我们设计应用程序时,它打算完成95%的集成工作,剩下的5%(实现类/App2)由熟悉第三方软件的顾问开发。

    public class Implemented : ClassToImplement{
        public override void DefinedMethod1(...);
        public override void DefinedMethod2(...);
    }
    

    “App”输出一个类库,然后在实现(App2)中引用该类库。在我们的设计中,我们创建了一个抽象类并定义了方法。当时的想法是,顾问将下载实施类的回购协议,并将该应用程序作为参考。然后,他们会为正在实现、编译和“瞧!”的方法编写必要的代码

    出于明显的原因,我不想与外部开发人员共享源项目,否则我只会共享完整的解决方案,并使用单个应用程序,而且,虽然我知道他们可以通过DLL引用看到很多内容,但对我们来说,控制一切都更容易。

    应用程序的问题是:主应用程序算法需要实例化实现类,然后程序才能完美运行。

    在表格1中。应用程序的cs:

    ClassToImplement impObj = new Implemented();
    impObj.DefinedMethod1();
    impObj.DefinedMethod2();
    

    我面临的挑战是,如果不实例化类,我无法构建“App”来输出DLL。我无法实例化实现的类,因为我还没有得到代码。

    如果知道如何依赖(尚未编写的)不成文的代码来实现这种抽象,以及我要做的事情的技术术语是什么,那就太好了?

    4 回复  |  直到 8 年前
        1
  •  1
  •   MineR    8 年前

    要使其“工作”,请使用一个Func,它返回抽象类的实例。

    在你的秘密回购协议中:

    //Your "App" DLL Project
    public abstract class ClassToImplement
    {
        public abstract void DefinedMethod1();
        public abstract void DefinedMethod2();
    }
    
    
    public class App : Form
    {
    
        public App(Func<ClassToImplement> initiator)
        {
            InitializeComponent();
    
            ClassToImplement ci = initiator.Invoke();
            ci.DefinedMethod1();
            ci.DefinedMethod2();
        }
    }
    
    
    //This is in a separate project which will be your startup project internally
    
    public class Dummy : ClassToImplement
    {
        public override void DefinedMethod1(){}
        public override void DefinedMethod2(){}
    }
    
    public class Program
    {
        public static void Main()
        {
            Application.Run(new App(()=> new Dummy()));
        }
    }
    

    在与顾问分享的回购协议中:

    // In the repo which is shared with the consultant
    // This will be the startup project on the build server, and when the consultant is testing.
    public class Implementation : ClassToImplement
    {
        public override void DefinedMethod1(){}
        public override void DefinedMethod2(){}
    }
    
    public class Program
    {
        public static void Main()
        {
            Application.Run(new App(()=> new Implementation()));
        }
    }
    

    在构建服务器上,您可以从两个repo中提取,并将启动项目设置为提供给顾问的项目。但是,当您在内部进行测试和开发时,您将启动项目设置为您的版本,而实现却什么都不做。

    作为补充说明,如果您认为您正在做的事情需要受到签署保密协议的顾问的保护,请确保在发布时混淆。

        2
  •  1
  •   Amit    8 年前

    这通常是一个两步过程:

    1. 找到并加载程序集/dll:

      Assembly assembly = Assembly.LoadFrom(DLL);
      
    2. 实例化实现的类:

      Type type = assembly.GetType(FullNameOfImplemented);
      AppInstance = (ClassToImplement)Activator.CreateInstance(type, parameters);
      
        3
  •  0
  •   Tom W    8 年前

    你正在寻找的过程通常被称为 stubbing .在本例中,您选择将集成功能封装在库中,而不是web服务中,但原理是相同的。

    当时的想法是,顾问将下载实施类的回购协议,并将该应用程序作为参考。

    这听起来好像你把依赖关系搞错了。如果顾问的代码引用了你的应用程序,那么你的应用程序就不能引用它——这将是一个循环依赖。取而代之的是,让你的应用程序更符合以下要求:

    App | | App.Integration.Contracts ^ ^ | | | App.Integration.Stub | App.Integration

    抽象类——它可以很容易地成为C#中的一个接口——驻留在Contracts程序集中。这是应用程序唯一的编译依赖项。然后 在运行时 使用配置加载存根,或者使用IoC容器加载完整的实现。例如 Unity 你需要它 configuration API .引用要在配置文件中使用的真实类型并进行更改 只有那个 更新应用程序以使用完整功能。

        4
  •  0
  •   Andre    8 年前

    首先,如果你不想和其他开发者分享你的代码,我认为你需要实现一个合适的插件系统。

    其次,您应该针对接口而不是其实现进行编码。第一个原因是你没有它,第二个原因是你可能想为不同的第三方软件切换实现。

    如果你需要一个用于测试的实例,你可以使用手写的mock或mock框架。如果您以后需要一个真实的实例(当其他开发人员交付时),您可以使用一些设计模式,比如factory模式或其他模式来创建。如果以后要更改实现,请尽量避免使用new关键字。

    推荐文章