有没有一种方法可以强制方法从其调用方继承作用域?

时间:2020-08-31 15:40:18

标签: c#

如果我有一个方法不在它的调用方范围内,它可以执行一些操作,则必须在多个位置多次调用此方法。有什么方法可以使调用方的整个范围对方法可用,而无需传递参数,也无需使用全局变量?就像我需要访问列表,实体框架上下文一样

代替

myMethod(string _string, List<string> _stringList, EntityContext _db)
{
    //log _string to a database table
    //add _string to _stringList
    //etc.
}

有没有一种方法可以让我通过_string并使该方法继承范围,就像我在调用此方法的任何地方都只是编写相同的三行代码一样?呼叫myMethod("foo")myMethod("foo", stringList, MyEntities)似乎更干净。

我可以创建一个类,实例化它,然后调用该类,但是我只是很想知道范围继承或范围传递是什么。

2 个答案:

答案 0 :(得分:3)

绝对不要那样做。如果您有需要传递的上下文,请使用一个类来表示所需的上下文,但不要尝试将其移开并隐藏。它使无法维护的代码具有相互依赖性。

实际上,传递上下文对象的“麻烦”或“开销”是一件好事:它指出在软件项目的元素之间具有依赖关系并不是免费的。如果您认为写出额外的参数是“太多的工作”,那么您就错过了树木的森林:这样引入的 dependency 的精神开销比单纯的打字机制要高得多一个额外的参数。几次传递该上下文后,键入它是第二自然,实际开销为0。打字很便宜,不需要思考,但是要记住依赖关系及其在整个系统设计中的重要性,只是什么。

因此:如果您试图证明引入依赖关系是值得的,那么您就必须用动作对其进行备份,并实际上传递上下文对象。实际成本在于依赖关系,而不是类型。否则,就是“通话便宜”的情况:)

降低传递此类上下文对象的表观“成本”的一种方法是破坏平衡,并使上下文对象实际执行某些操作,而不仅仅是携带数据。然后,您将使用上下文对象为您操纵对象,而不是调用对象上的方法。这种“反转”非常方便,并且通常可以带来更好的设计。毕竟,上下文的存在表明存在一个总体上的公共状态,并且可能将过多的功能委派给“最终对象”,使其与公共状态交织在一起,而在上下文对象中它可能更有意义,使最终对象较​​少依赖于任何特定外部状态的存在。

您希望上下文具有需要“了解全局”的方法,即知道存在多个对象,而“叶对象”(带有myMethod的对象)应具有方法不需要上下文,或者足够通用而不会强制使用任何特定的上下文类。

在您的情况下,myMethod可能会生成函子或执行操作的类似操作包装对象,而不是直接在EntityContext上进行操作,然后可以由调用方应用(例如上下文)来执行数据库操作。这样一来,以后集中管理数据库操作队列等会变得更加容易。

当我重构大型项目时,这种“上下文倒置”经常派上用场,并且对这种模式的需求非常普遍。通常,随着大型项目的发展,“叶类”开始精简,最终获得更高级别的功能。这就是为什么必须使用良好的工具来探索存储库的历史记录的原因,并且整个存储库历史记录可用(即已将其正确导入到git中)同样重要。我个人使用DeepGit来跟踪我正在处理的代码的历史,并发现必不可少的此类工具。 DeepGit可以像啤酒一样免费使用,如果您不使用具有类似功能的工具,那么我会严重地错过这个机会。

需要传递上下文通常是指示必须设计和引入更高级别的指示,然后需要精简“叶子”,将其使用上下文的功能移到更高级别。几年之后,仍然需要更高的层次,尽管到目前为止已经有一些项目消失了,当您仅重构它们以理解代码库时,就会再增加两到三层!

答案 1 :(得分:0)

我知道有两种方法可以完成。考虑您具有以下方法:

    static void myMethod(string _stringA, string _stringB, string _stringC)
    {
        Console.WriteLine($"{_stringA},{_stringB},{_stringC}");
    }
  1. 在类中创建一个重载方法。例如,您可以创建一个重载方法,例如:

     static void myMethod(string _stringA)
     {
         myMethod(_stringA, "stringB", "stringC");
     }
    
  2. 第二种方法(我不建议这样做)是像Javascript一样的功能方法(通过使用委托):

     public delegate void MethodDelegate(string _string);
     static MethodDelegate mMethod1;
     static MethodDelegate mMethod2;
    
     static void Main(string[] args)
     {
         mMethod1 = delegate (string s) { myMethod(s, "method1-str-a", "method1-str-b"); };
         mMethod1("str1");
         mMethod2 = delegate (string s) { myMethod(s, "method2-str-a", "method2-str-b"); };
         mMethod2("str2");
     }