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

时间:2018-05-29 09:37:11

标签: c# winforms oop abstract-class

我有一个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)中引用。在我们的设计中,我们创建了一个抽象类并定义了方法。这个想法是顾问会下载实现类的repo并包含App作为参考。然后他们会为他们正在实现的方法编写必要的代码,编译并“瞧!”

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

问题来自App:主应用程序算法需要实例化实现类,然后程序运行完美。

在App的Form1.cs中

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

我遇到的挑战是我无法构建“App”来输出DLL而不实例化Class。我无法实例化Implemented Class,因为我还没有得到代码。

很高兴知道如何通过依赖(但)不成文的代码来实现这种抽象,以及我正在尝试做什么的技术术语?

4 个答案:

答案 0 :(得分:1)

这通常是两步过程:

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

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

    Type type = assembly.GetType(FullNameOfImplemented);
    AppInstance = (ClassToImplement)Activator.CreateInstance(type, parameters);
    

答案 1 :(得分:1)

要使它只是“工作”,请使用返回抽象类实例的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()));
    }
}

在构建服务器上,您可以从两个存储库中取出,并将启动项目设置为给予顾问的项目。但是,当您在内部进行测试和开发时,可以将启动项目设置为您的版本,其实现不执行任何操作。

作为旁注,如果您认为您正在做的事情需要保护,以免签署保密协议的顾问,请务必在发布时进行模糊处理。

答案 2 :(得分:0)

您正在寻找的流程通常称为stubbing。在这种情况下,您已选择将集成功能封装在库中,而不是Web服务中,但原理是相同的。

  

这个想法是顾问会为实现类下载repo并将App作为参考包含。

这听起来像是你的依赖关系是错误的。如果顾问的代码引用了您的应用,那么您的应用无法引用它 - 它将成为循环依赖。相反,请根据以下内容对您的应用进行更多考虑:

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

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

答案 3 :(得分:0)

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

其次,您应该针对您的界面进行编码,而不是针对其实现。首先是因为你没有它,其次是因为你可能想要切换不同第三方软件的实现。

如果您需要测试或填充实例,可以使用手写模拟或模拟框架。如果您以后需要一个真实的实例(当其他开发人员交付时),您可以使用一些设计模式,如工厂模式或其他设计模式来创建。如果您想稍后更改实现,请尝试避免使用new关键字。