如何在不改变方法用法的情况下将 class 移动到另一个 dll 并更改命名空间

How to Move a class to another dll and change the namespace without altering the method usage

我有一个 dll,其中有一个 class 记录到 "channel",另一个程序侦听 "channel" 并将日志写入屏幕。 dll 的问题是它随着时间的推移而增长,现在它有很多依赖项。我想从这个 dll 中删除日志记录部分并将其放在调试和日志记录 dll 中。

问题是调试和日志记录 dll 有另一个我想在 class 中使用的名称空间,或者我想在名称空间中使用 class。我的问题是,一些开发人员在调用方法时几乎只使用命名空间,而不是在 classes.

的顶部使用它

静态方法看起来像下面这样:

Base.Manager.Logging.Send("Log something");

另一个 Dll 具有简单的命名空间 Trace 所以它应该是这样的:

Trace.Logging.Send("Log something");

我的问题是,是否有一种优雅的方式来移动 class 并更改名称空间而不改变方法的所有用途? 我可以简单地将 class 复制到另一个 dll,然后使用旧的 class 作为包装器,将所有调用转发给 Trace.dll 中的另一个 class 但是这种方法似乎有点老套。

我希望这张图能说明我的意思,因为我认为简单的文字可能有点令人困惑

仅供参考:我没有 ReSharper

很遗憾,你不能。如果您保留相同的命名空间,那么您可以使用 TypeForwardAttribute 但如果您还更改命名空间(不仅仅是程序集),那么它就不起作用。

我的建议是将它移动到新的 class,保留旧的 class 以免在 运行 时和编译时破坏代码并转发所有调用.将所有旧方法标记为 obsolete(至少他们会被警告代码将来会更改)。澄清一下:

namespace Base.Manager {
    public static class Logger {
        public static void Send(string message) { 
            // Do things
        }
    }

第 1 步:清空旧的已弃用 class 并将呼叫转移到新的 class。将旧方法标记为过时。

然后将被重构为:

namespace Base.Manager {
    [EditorBrowsable(EditorBrowsableState.Never)]
    public static class Logger {
        [Obsolete("This method is deprecated, please use Trace.Logger.Send")]
        public static void Send(string message) {
            // Delegate work to someone else...
            Trace.Logger.Send(message);
        }
    }

它会在编译过程中生成一个警告(带有给定的消息)。 编译时兼容性 已保存。请注意,我们还添加了 EditorBrowsableAttribute,IntelliSense 不会在他们开始键入时建议 Logger class。这减少了(一点点)他们仍将 Base.Manager.Logger 用于新代码的机会。

第 2 步:将来有一天您会将警告更改为错误:

[Obsolete("This method is obsolete, use Trace.Logger.Send", true)]

这会破坏编译,但会保持二进制兼容性。其他 DLL 仍将 运行(因此您不必等待其他开发人员完成此重构任务)但除非更新,否则它们将无法编译。

第 3 步:当所有操作都完成并且每个人都转移到新的 class 后,只需从您的代码中删除 Base.Manager.Logger class。

注释:所有过程都可以跨越不同的版本:在 2.0 中你弃用了旧方法,在 2.1 中你破坏了编译,在 3.0 中你将它从你的代码中删除(这如果您的代码发布与其用户不同步,则此功能特别有用。

关于名称冲突的简单说明:请注意,两个不同名称空间中的相同 class 名称(和方法)可能会导致恼人的名称冲突。想象一下他们有这样的代码:

using Base.Manager;

void DoSomething() {
    Logger.Send("I'm doing something.");
}

在您更改之后(直到 Base.Manager.Logger 未被删除)他们不能简单地添加另一个 using:

using Base.Manager;
using Trace;

void DoSomething() {
    Base.Manager.SomethingElse.DoIt();

    // Compiler is confused: Base.Manager.Logger or Trace.Logger?
    Logger.Send("I'm doing something.");
}

他们需要完全限定他们想要使用的记录器 class:

Trace.Logger.Send("I'm doing something.");

警告:请注意,如果 Trace 不是新的命名空间,那么如果它们同时具有两个 using,则名称冲突甚至可能会立即中断编译在他们的代码中(使 ObsoleteAttribute 无用)。

如果这对 you/your 用户来说是个问题...我不能说。