【问题标题】:Check if code is called from Windows Forms Application [duplicate]检查是否从 Windows 窗体应用程序调用代码 [重复]
【发布时间】:2016-02-12 20:58:21
【问题描述】:

我有一个从 Web 服务、服务或 Windows 窗体应用程序调用的类库。

对于 windows 窗体应用程序,我想为 web 服务和服务显示一个是/否消息框,我只想假设是。

我知道我可以重构我的代码以使用抽象层,例如

var provider = new MessageBoxProvider(); // Or other implementation
var result = provider.QueryResult(...);

但除此之外:

有没有更好的方法来检查代码是否从 Windows 应用程序调用?目前我在做

System.Windows.Forms.Application.OpenForms.Count > 0

【问题讨论】:

  • 我不确定您的库中是否需要任何 ui 逻辑,是否可以将其重构为仅返回一条消息并让调用者处理它?
  • 这看起来像是一个 XY 问题,并且存在许多解决方案来防止您首先需要将库代码绑定到特定的 UI 框架。除了抽象层之外,您还可以创建调用应用程序可以订阅的事件或回调。
  • 另请参阅Work out the type of c# application a class contained in a DLL is being used by,其中还存在所有当前答案以及有关潜在缺点等的更多信息。

标签: c# winforms web-services


【解决方案1】:

我使用System.Environment.UserInteractive 进行这种检查。

如果我没记错的话,这对于 Windows 应用程序返回 true,对于 Windows 服务、Web 应用程序和 Web 服务返回 false。 (控制台应用程序呢?我应该检查一下)

我同意你应该以不同的方式解决它,正如其他人所指出的那样

【讨论】:

  • 对于控制台应用程序返回 true,我忘了这个,听起来不错。
  • tks @TheLethalCoder。多想一下,它不应该取决于我认为的应用程序类型,它取决于它在操作系统中的运行方式。如果您从命令提示符启动控制台应用程序,则 UserInteractive 为 true,但我怀疑如果您将其作为窗口计划任务启动,则为 false。
【解决方案2】:

我宁愿使用依赖注入,在其中将带有方法的接口传递给类,因此它也可以在单元测试中进行测试,并且可以从 Windows 窗体应用程序进行设置,而不依赖于该类中的 Windows 窗体内容。我想这就像你的抽象层。

public interface IMessageHandler
{
    void SendMessage(string message);
}

public class WindowsFormsMessageHandler : IMessageHandler
{
    public void SendMessage(string message)
    {
        System.Windows.Forms.MessageBox.Show(message);
    }
}

public class OuterClass
{
    private IMessageHandler _handler;

    public OuterClass(IMessageHandler handler)
    {
        if (handler == null)
            throw new ArgumentNullException("handler");

        _handler = handler;
    }

    public void DoSomething()
    {
        _handler.SendMessage("Hello");
    }    
}

...

var testClassInWindowsForms = new OuterClass(new WindowsFormsMessageHandler());

test.DoSomething();

通过这样做,您可以根据您来自哪里的实现来更改行为,而不是依赖可能不可靠的检查。

【讨论】:

  • 这是回答什么问题?依赖注入在哪里发挥作用?
  • 不要在你的类中进行(不可靠的)检测,而是提供一个将消息发送到的接口。
  • 我更新了一个代码示例!这可以防止您将 Windows 表单内容拖到您的班级中,并防止它依赖于将来可能会更改的检查。
【解决方案3】:

你可以只向类库传递一个布尔值,例如:

new ClassLibrary(true);

当它是一个 WinForms 应用程序时。

然后有类似下面的构造函数

ClassLibrary(bool calledFromWinforms)

我知道这不是最好的代码,但它使事情变得简单并且不会使它们过于复杂。

【讨论】:

  • 我认为它使它变得更复杂,这意味着库仍然需要引用 winforms 类,并且调用者不清楚为什么如果从 winforms 调用它会有所作为与否。
  • @Sayse 就像我说的不是最好的代码,而是一种“解决”问题的方法,如果你想让它更清楚,可以随时将其更改为 bool showMessageBox
  • 当然,但我不认为它解决了问题,它只是把它推到其他地方
【解决方案4】:

我的方法是向类添加一个属性,该属性在实例化时设置自身并存储其运行所在的环境类型。稍后可以使用该属性来识别从何处调用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多