如果我有一个方法不在它的调用方范围内,它可以执行一些操作,则必须在多个位置多次调用此方法。有什么方法可以使调用方的整个范围对方法可用,而无需传递参数,也无需使用全局变量?就像我需要访问列表,实体框架上下文一样
代替
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)
似乎更干净。
我可以创建一个类,实例化它,然后调用该类,但是我只是很想知道范围继承或范围传递是什么。
答案 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}");
}
在类中创建一个重载方法。例如,您可以创建一个重载方法,例如:
static void myMethod(string _stringA)
{
myMethod(_stringA, "stringB", "stringC");
}
第二种方法(我不建议这样做)是像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");
}