backup the current project
"""convert code to markdown """ import datetime import os import platform import re import shutil class CodeToMarkDown: """_summary_""" __slots__ = ["path", "md_path", "code_file_path", "exclude_dirs", "exclude_files", "md_suffix_table", "include_exts", "key_work_filter_list"] def __init__(self, path: str = None) -> None: if path: self.path = path else: self.path = os.getcwd() # 需要排除的目录 self.exclude_dirs = [ "__pycache__", "venv", "build", "dist", "node_modules", "public", "LICENSE", "assets", "vendor", "tmp", "static", "templates", "bin", "obj", "Migrations", "Properties", "packages", ] # 排除的文件的后缀 self.exclude_files = [ "_NOTE.md", ".d.ts", ".lock", ".png", ".woff2", ".ttf", ".woff", ".css", "README.md", ".toml", "swagger-ui-bundle.js", "-lock.json", "zz_code2md.py", "zz.py", "temp.md", ] # 文件后缀名对应的 md code代码提示名 self.md_suffix_table = {"command": "sh", "csproj": "xml"} # 需要包含的文件后缀名 self.include_exts = [ ".py", ".vue", ".js", ".ts", ".html", ".go", ".mod", ".json", ".txt", ".sh", ".command", ".cs", "csproj", ".jsx", ".sln", ".sh", ".bat", ] # 需要过滤的文件名的后缀 self.key_work_filter_list = [""] def generate_md(self): self.__generate_md_file_path() self.__collect_code_files() self.__generate_md_file() def __generate_md_file_path(self): cur_time_str = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") md_name = f"Z_{cur_time_str}_NOTE.md" self.md_path = os.path.join(self.path, md_name) def __collect_code_files(self): """_summary_ Returns: _type_: _description_ """ self.code_file_path = [] for root, dirs, files in os.walk(self.path): # 过滤不符合的文件夹------------------------------------------------------------------------ dirs[:] = [d for d in dirs if not d.startswith(".") and not any(ex in d for ex in self.exclude_dirs)] # 过滤不符合的文件----------------------------------------------------------------------------- files[:] = [f for f in files if not f.startswith(".") and not any(ex in f for ex in self.exclude_files)] # 筛选所有符合后缀的文件------------------------------------------------------------------------ for file in files: # 正向过滤含有(\.py|vue|js|ts)$ 结尾的文件 if any(file.endswith(ext) for ext in self.include_exts): self.code_file_path.append(os.path.join(root, file)) def __generate_md_file(self): for i, code_file_path in enumerate(self.code_file_path): print(i + 1, "->", self.__get_md_title_level_one(code_file_path)) self.__readcode_writemd(code_file_path) def __get_md_title_level_one(self, code_file_path): """获取每个代码文件的md标题,去掉项目之前的文件路径 Args: code_file_path (_type_): 代码路径 project_path (_type_): 项目根路径 Returns: _type_: 每个代码文件的md标题 """ # Get the common prefix of the two paths common_prefix = os.path.commonprefix([code_file_path, self.path]) # Get the different parts of the two paths diff1 = code_file_path[len(common_prefix) + 1 :] md_title = os.path.join(os.path.basename(self.path), diff1) return md_title def __readcode_writemd(self, code_file_path): """_summary_ Args: code_file_path (_type_): _description_ """ with open(code_file_path, "r", encoding="utf-8") as f: # 打开文件 try: content = f.read() except Exception as e: print(f"{code_file_path}{e}文件编码读取错误") content = "" self.__write2md(content, code_file_path) def __write2md( self, content, code_file_path, ): """_summary_ Args: content (_type_): _description_ suffix (_type_): _description_ code_file_path (_type_): _description_ """ with open(self.md_path, "a", encoding="utf-8") as f: # 打开文件 md_title_level_one = self.__get_md_title_level_one(code_file_path) code_label = self.__get_code_md_lable_by_suffix(code_file_path) f.write("\n") f.write(f"# `{md_title_level_one}`\n\n") f.write(f"```{code_label}\n") f.write(content) f.write("\n") f.write("```\n\n\n") def __get_code_md_lable_by_suffix(self, code_file_path): suffix = re.findall(r'\.[^.\\/:*?"<>|\r\n]+$', code_file_path) if len(suffix): suffix = suffix[0][1:] if self.md_suffix_table.get(suffix) is not None: return self.md_suffix_table.get(suffix) return suffix class MarkdownToCode: """_summary_ Returns: _type_: _description_ """ __slots__ = ["path", "base_dir"] def __init__(self, path: str = None) -> None: if path: self.path = path else: self.path = self.__get_latest_md_file_path() def __get_latest_md_file_path(self): dst_md_files = [] for root, _, files in os.walk(os.getcwd()): for file in files: if file.endswith("_NOTE.md"): dst_md_files.append(os.path.join(root, file)) return sorted(dst_md_files).pop() def generate_code(self): self.__set_base_dir() self.__read_md_file() def __read_md_file(self): """_summary_""" with open(self.path, "r", encoding="utf-8") as f: # 打开文件 md_text = f.read() # Match the first-level headings and code blocks # \n{1,}# `(.+)`\n{1,}```\w{2,5}\n{1,} pattern = r"^# `(.+)`\n{1,}```(?:\w{2,}\n)([\s\S]+?)\n{1,}```\n{1,}" matches = re.findall(pattern, md_text, re.MULTILINE) # Loop over the matches for i, (file_path, code) in enumerate(matches): print(f"{i}->", file_path) self.__create_from_file_path(file_path, code) def __set_base_dir(self): self.base_dir = os.path.dirname(self.path) def __create_from_file_path(self, file_path, content): """_summary_ Args: file_path (_type_): _description_ content (_type_): _description_ """ dir_path = os.path.join(self.base_dir, os.path.dirname(file_path)) os.makedirs(dir_path, exist_ok=True) full_file_path = os.path.join(self.base_dir, file_path) with open(full_file_path, "w", encoding="utf-8") as f: f.write(content) class CollectMarkdownNote: """_summary_""" __slots__ = [ "path", "md_path", "cur_file_name", "cur_file_new_name", "md_files", "dotnet_md_files", "python_md_files", "dotnet_line_number_start", "dotnet_split_flag", "dotnet_file_names", "python_split_flag", "current_new_md_file_name", "save_md_file_heads", "split_flag", "other_split_flag", "other_md_files", ] def __init__(self, path: str = None) -> None: if path: self.path = path else: self.path = os.getcwd() self.dotnet_line_number_start = [] self.dotnet_file_names = [] self.current_new_md_file_name = None # 需要保留的markdown文件的开头 # self.save_md_file_heads = ["zz_dotnet", "zz_python", "zz_csharp", "zz_note", "zz_"] self.save_md_file_heads = ["zz_"] # 需要需要的markdown文件,zz_开头,不在zz_note里面的markdown文件 self.md_files = [] # 需要收集的关于dotent的md文件,zz_开头,不在zz_note里面 self.dotnet_md_files = [] # 需要收集的关于python的md文件,zz_开头,不在zz_note里面 self.python_md_files = [] # 需要收集的关于python的md文件,zz_开头,不在zz_note里面 self.other_md_files = [] # 即将生成的python文件的文件名,就是当前文件的文件夹,加上时间戳的后缀 self.cur_file_new_name = None # 当前这个python脚本的文件名 self.cur_file_name = os.path.basename(__file__) def collect_markdown(self): """收集当前项目中的markdown笔记""" self.__get_new_python_file_name() self.__get_cur_markdown_notes() self.__read_cur_markdown_notes() self.__generate_new_python_file() def __write2md(self, line): # 如我文件名不为空,代表可以写入,同时要过滤到python中的注释符号,防止python脚本出现错误 if (self.current_new_md_file_name is not None) and line != '"""\n' and line != '"""' and line != '\n"""': nf = open(self.current_new_md_file_name, "a+", encoding="utf-8") nf.write(line) nf.close() def un_collect_markdown(self): """doc""" f = open(self.cur_file_name, "r", encoding="utf-8") for i, line in enumerate(f): self.__write2md(line) res = re.findall(re.compile(r"^\"\"\"#==(.{1,10})=="), line) if len(res) > 0: self.current_new_md_file_name = self.__get_output_md_file_name_by_line(line) print(i + 1, "->", self.current_new_md_file_name, "start") if line.startswith('"""\n'): print(i + 1, "->", self.current_new_md_file_name, "end") self.current_new_md_file_name = None def __get_output_md_file_name_by_line(self, line): # 输出zz_note的子文件夹的名称,从"""==python==提取 dir_name = "other" name = "other" pattern = re.compile(r"^\"\"\"#==(.{1,10})==(.+).md") res = pattern.match(line) if res: dir_name = res.groups()[0] name = res.groups()[1] # 生成markdown文件的后缀名,防止冲突 cur_time_str = str(datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")) # 生成的markdown文件的文件夹,zz_note/python,或者给zz_dotnet,取决于什么类型的文件 dir_path = os.path.join("zz_note", dir_name) os.makedirs(dir_path, exist_ok=True) return "zz_note/" + dir_name + "/" + name + "_" + cur_time_str + ".md" def __read_cur_markdown_notes(self): """_summary_""" for md_file in self.md_files: if "dotnet" in md_file: self.dotnet_md_files.append(md_file) elif "python" in md_file: self.python_md_files.append(md_file) elif "other" in md_file: self.other_md_files.append(md_file) def __get_cur_markdown_notes(self): """_summary_""" print("开始收集,所以以zz_开头的,不在zz_note文件夹中的markdown文件") pattern = re.compile(r"zz_(\w+)_") for root, dirs, files in os.walk(self.path): dirs[:] = [d for d in dirs if "zz_note" not in d] # 过滤符合的文件----------------------------------------------------------------------------- files[:] = [f for f in files if not f.startswith(".") and any(ex in f for ex in [".md"])] # 筛选所有符合后缀的文件------------------------------------------------------------------------ for i, file in enumerate(files): print(i + 1, "->", file) res = pattern.findall(file) if len(res) > 0: self.md_files.append(os.path.join(root, file)) def __get_new_python_file_name(self): cur_time_str = str(datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")) file_names = self.cur_file_name.split("_") if len(file_names) > 1: self.cur_file_new_name = f"{os.path.splitext(file_names[0])[0]}_{cur_time_str}.py" else: self.cur_file_new_name = f"{os.path.splitext(self.cur_file_name)[0]}_{cur_time_str}.py" def __get_cur_file_name(self, md_file_path): return os.path.basename(md_file_path) def __generate_new_python_file(self): """_summary_""" f = open(self.cur_file_name, "r", encoding="utf-8") for line in f: nf = open(self.cur_file_new_name, "a+", encoding="utf-8") nf.write(line) for md_file in self.md_files: split_flag = "other" pattern = re.compile(r"zz_(\w+)_") res = pattern.findall(md_file) if len(res) > 0: split_flag = res[0] md_title = self.__get_cur_file_name(md_file) content = self.__read_md_file(md_file) nf.write(f'\n\n"""#=={split_flag}=={md_title}\n\n') nf.write(self.__filter_python_comment(content)) nf.write('\n"""\n\n') f.close() nf.close() # 备份新生成的python文件 self.__copy_current_python_file_to_dst_dir(self.cur_file_new_name) def __copy_current_python_file_to_dst_dir(self, current_python_file_name): """备份新生成的python文件,到特定的文件夹 Args: current_python_file_name (_type_): _description_ """ system = platform.system() if system == "Windows": dir_path = r"D:/zz" os.makedirs(dir_path, exist_ok=True) shutil.copy(current_python_file_name, os.path.join(dir_path, current_python_file_name)) elif system == "Darwin": dir_path = r"/Users/song/Code/zz_note" os.makedirs(dir_path, exist_ok=True) shutil.copy(current_python_file_name, os.path.join(dir_path, current_python_file_name)) else: print("Unknown system") def __filter_python_comment(self, content: str): return content.replace('"""', "") def __read_md_file(self, file): with open(file, "r", encoding="utf-8") as f: content = f.read() return content def backup_current_project(): """_summary_""" src_dir = os.path.dirname(__file__) cur_time_str = str(datetime.datetime.now().strftime("%Y%m%d_%H%M%S")) compress_filename = f"{os.path.basename(src_dir)}_{cur_time_str}" dst_dir = os.path.join( os.path.dirname(os.path.dirname(__file__)), compress_filename, ) shutil.copytree(src_dir, dst_dir) if __name__ == "__main__": print("===============================start===============================") print("1. Project Convert to Markdown 2. Markdown Convert to Project") print("3. Collect Markdown Notes 4. Uncollect Markdown Notes") print("5. Backup the project ") try: option_number = int(input("Please input a number: ")) except Exception as e: option_number = 0 print("您输入的整数是:", option_number) if option_number == 1: code2md = CodeToMarkDown() code2md.generate_md() elif option_number == 2: md_path = input("请输入需要转换的markdown文件路径(默认使用当前路径最新的markdown文件) : ") md2code = MarkdownToCode(md_path) md2code.generate_code() elif option_number == 3: collect_md = CollectMarkdownNote() collect_md.collect_markdown() elif option_number == 4: is_del = input("是否要删除现有的文件夹(Y/N):") if is_del == "N" or is_del == "n": pass else: try: res = shutil.rmtree("zz_note") print("zz_note文件夹,删除成功") except FileNotFoundError as e: print("no such directory,zz_note") collect_md = CollectMarkdownNote() collect_md.un_collect_markdown() elif option_number == 5: backup_current_project() else: print("unknown option") print("===============================done===============================") # ================================================================================================ """#==python==zz_python_的vscode配置.md # `.vscode/.Pylintrc` ```sh # This Pylint rcfile contains a best-effort configuration to uphold the # best-practices and style described in the Google Python style guide: # https://google.github.io/styleguide/pyguide.html # # Its canonical open-source location is: # https://google.github.io/styleguide/pylintrc [MASTER] # Files or directories to be skipped. They should be base names, not paths. ignore=third_party # Files or directories matching the regex patterns are skipped. The regex # matches against base names, not paths. ignore-patterns= # Pickle collected data for later comparisons. persistent=no # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins= # Use multiple processes to speed up Pylint. jobs=4 # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED confidence= # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. #enable= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once).You can also use "--disable=all" to # disable everything first and then reenable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" disable=abstract-method, broad-exception-caught, missing-module-docstring, apply-builtin, arguments-differ, attribute-defined-outside-init, backtick, bad-option-value, basestring-builtin, buffer-builtin, c-extension-no-member, consider-using-enumerate, cmp-builtin, cmp-method, coerce-builtin, coerce-method, delslice-method, div-method, duplicate-code, eq-without-hash, execfile-builtin, file-builtin, filter-builtin-not-iterating, fixme, getslice-method, global-statement, hex-method, idiv-method, implicit-str-concat, import-error, import-self, import-star-module-level, inconsistent-return-statements, input-builtin, intern-builtin, invalid-str-codec, locally-disabled, long-builtin, long-suffix, map-builtin-not-iterating, misplaced-comparison-constant, metaclass-assignment, next-method-called, next-method-defined, no-absolute-import, no-else-break, no-else-continue, no-else-raise, no-else-return, no-init, # added no-member, no-name-in-module, no-self-use, nonzero-method, oct-method, old-division, old-ne-operator, old-octal-literal, old-raise-syntax, parameter-unpacking, print-statement, raising-string, range-builtin-not-iterating, raw_input-builtin, rdiv-method, reduce-builtin, relative-import, reload-builtin, round-builtin, setslice-method, signature-differs, standarderror-builtin, suppressed-message, sys-max-int, too-few-public-methods, too-many-ancestors, too-many-arguments, too-many-boolean-expressions, too-many-branches, too-many-instance-attributes, too-many-locals, too-many-nested-blocks, too-many-public-methods, too-many-return-statements, too-many-statements, trailing-newlines, unichr-builtin, unicode-builtin, unnecessary-pass, unpacking-in-except, useless-else-on-loop, useless-object-inheritance, useless-suppression, using-cmp-argument, wrong-import-order, xrange-builtin, zip-builtin-not-iterating, [REPORTS] # Set the output format. Available formats are text, parseable, colorized, msvs # (visual studio) and html. You can also give a reporter class, eg # mypackage.mymodule.MyReporterClass. output-format=text # Tells whether to display a full report or only the messages reports=no # Python expression which should return a note less than 10 (10 is the highest # note). You have access to the variables errors warning, statement which # respectively contain the number of errors / warnings messages and the total # number of statements analyzed. This is used by the global evaluation report # (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details #msg-template= [BASIC] # Good variable names which should always be accepted, separated by a comma good-names=main,_ # Bad variable names which should always be refused, separated by a comma bad-names= # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Include a hint for the correct naming format with invalid-name include-naming-hint=no # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl # Regular expression matching correct function names function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$ # Regular expression matching correct variable names variable-rgx=^[a-z][a-z0-9_]*$ # Regular expression matching correct constant names const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ # Regular expression matching correct attribute names attr-rgx=^_{0,2}[a-z][a-z0-9_]*$ # Regular expression matching correct argument names argument-rgx=^[a-z][a-z0-9_]*$ # Regular expression matching correct class attribute names class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ # Regular expression matching correct inline iteration names inlinevar-rgx=^[a-z][a-z0-9_]*$ # Regular expression matching correct class names class-rgx=^_?[A-Z][a-zA-Z0-9]*$ # Regular expression matching correct module names module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$ # Regular expression matching correct method names method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$ # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$ # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=10 [TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). ignore-mixin-members=yes # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching. ignored-modules= # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=optparse.Values,thread._local,_thread._local # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= [FORMAT] # Maximum number of characters on a single line. max-line-length=150 # TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt # lines made too long by directives to pytype. # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=(?x)( ^\s*(\#\ )?<?https?://\S+>?$| ^\s*(from\s+\S+\s+)?import\s+.+$) # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=yes # Maximum number of lines in a module max-module-lines=99999 # String used as indentation unit. The internal Google style guide mandates 2 # spaces. Google's externaly-published style guide says 4, consistent with # PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google # projects (like TensorFlow). indent-string=' ' # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=TODO [STRING] # This flag controls whether inconsistent-quotes generates a warning when the # character used as a quote delimiter is used inconsistently within a module. check-quote-consistency=yes [VARIABLES] # Tells whether we should check for unused import in __init__ files. init-import=no # A regular expression matching the name of dummy variables (i.e. expectedly # not used). dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_) # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_,_cb # List of qualified module names which can have objects that can redefine # builtins. redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools [LOGGING] # Logging modules to check that the string format arguments are in logging # function parameter format logging-modules=logging,absl.logging,tensorflow.io.logging [SIMILARITIES] # Minimum lines number of a similarity. min-similarity-lines=4 # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no [SPELLING] # Spelling dictionary name. Available dictionaries: none. To make it working # install python-enchant package. spelling-dict= # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to indicated private dictionary in # --spelling-private-dict-file option instead of raising a message. spelling-store-unknown-words=no [IMPORTS] # Deprecated modules which should not be used, separated by a comma deprecated-modules=regsub, TERMIOS, Bastion, rexec, sets # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled) import-graph= # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled) ext-import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= # Force import order to recognize a module as part of the standard # compatibility libraries. known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant, absl # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__, __new__, setUp # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict, _fields, _replace, _source, _make # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls, class_ # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=mcs [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "Exception" overgeneral-exceptions=builtins.StandardError, builtins.Exception, builtins.BaseException
.vscode/settings.json
{ "python.analysis.autoImportCompletions": true, // 若要为安装在非标准位置的包启用 IntelliSense,请将这些位置添加到 settings.json 文件中的 python.analysis.extraPaths 集合中(默认集合为空)。 // 例如,您可能已将 Google App Engine 安装在自定义位置,在本例中,请按如下方式指定这些位置: // "python.analysis.extraPaths": [ // "C:/Program Files (x86)/Google/google_appengine", // "C:/Program Files (x86)/Google/google_appengine/lib/flask-0.12"] // "python.analysis.extraPaths": [], "python.analysis.packageIndexDepths": [ { "name": "fastapi", "depth": 2 }, { "name": "selenium", "depth": 2, "includeAllSymbols": false } ], // "pylint.path": ["${workspaceFolder}/.venv/bin", "-m", "pylint"], // pylint的配置 "pylint.args": ["--rcfile=${workspaceFolder}/.vscode/.pylintrc"], "[python]": { "diffEditor.ignoreTrimWhitespace": false, "editor.formatOnType": true, "editor.formatOnSave": true, "editor.formatOnPaste": true, "editor.wordBasedSuggestions": "off", // "editor.defaultFormatter": "ms-python.pylint", "editor.defaultFormatter": "ms-python.black-formatter", "editor.codeActionsOnSave": { "source.organizeImports": "explicit" } }, "black-formatter.args": ["--line-length=150"], "editor.tabSize": 2, "isort.args": [ "--profile", "black" ], "dotnet.defaultSolution": "dotnet_agv_back.sln" }
"""
"""#pythonzz_python_运行脚本bat_shell脚本.md
bat脚本传递文件路径给python脚本
简单版本
@echo off :start set filePath= set /p filePath=Please input file path: python main.py %filePath% goto start
指定python的版本(Python虚拟环境)
@echo off :start set filePath= set /p filePath=Please input file path: D:\Python38\python E:\song\python_code2md\md2code\md2code.py %filePath% goto start
shell脚本运行python(mac系统)
#! /bin/bash # 激活虚拟环境,安装目前的情况,不需要虚拟环境,也可以实现 # source /home/song/venv/bin/activate echo "请拖入一个代码项目根目录的文件或者文件夹:" read file python3 /Users/song/Code/script_python/code2md/md2code.py "$file" # 等待五秒钟,然后自动关闭 sleep 3 osascript -e 'tell application "Terminal" to close first window' & exit
"""
"""#pythonzz_python_的gitignore文件.md
.gitignore
### Python template # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/
"""
"""#dotnetzz_dotnet_ef工具使用.md
EF Core
# 为模型的更改添加一个新的迁移 dotnet ef migrations add <NAME> # 删除上一个迁移 dotnet ef migrations remove # 列出所有的迁移 dotnet ef migrations list # 生成一个SQL脚本,用于将数据库更新到指定的迁移 dotnet ef migrations script # 将数据库更新到指定的迁移或最新的迁移 dotnet ef database update # 删除数据库 dotnet ef database drop # 从现有数据库生成模型 dotnet ef dbcontext scaffold <CONNECTION> <PROVIDER> # 获取当前的DbContext的信息 dotnet ef dbcontext info # 列出项目中的所有DbContext dotnet ef dbcontext list
"""
"""#dotnetzz_dotnet_升级助手.md
.NET 升级助手
安装并运行升级助手
dotnet tool install -g upgrade-assistant
升级项目
upgrade-assistant upgrade <Path to Project>
"""
"""#dotnetzz_dotnet_的依赖注入.md
原先的模式
GamesEndpoints.cs
public static class GamesEndpoints { public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints) { // 自动创建一个实例,然后使用 InMemGamesRepository repository = new(); var group = endpoints.MapGroup("/games").WithParameterValidation(); group.MapGet("/", () => repository.GetAll()); return group; } }
InMemGamesRepository.cs
using GameStore.Api.Entities; namespace GameStore.Api.Repositoriesa; public class InMemGamesRepository { private readonly List<Game> games = new() { new Game(){ Id = 1, Name="Street Fighter II", Genre ="Fighting", Price = 19.99M, ReleaseDate = new DateTime(1991,2,1), ImgUri = "https://palcehold.co/100" }, new Game(){ Id = 2, Name="FIFA 23", Genre ="Sports", Price = 29.99M, ReleaseDate = new DateTime(2022,2,1), ImgUri = "https://palcehold.co/100" }, }; public IEnumerable<Game> GetAll() { return games; } public Game? Get(int id) { return games.Find(game => game.Id == id); } public void Create(Game game) { game.Id = games.Max(game => game.Id) + 1; games.Add(game); } public void Update(Game updatedGame) { var index = games.FindIndex(game => game.Id == updatedGame.Id); games[index] = updatedGame; } public void Delete(int id) { var index = games.FindIndex(game => game.Id == id); games.RemoveAt(index); } }
现在的模式
GamesEndpoints.cs
using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata; using GameStore.Api.Entities; using GameStore.Api.Repositoriesa; namespace GameStore.Api.Endpoints; public static class GamesEndpoints { const string GetGameEndpointName = "GetGame"; public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints) { var group = endpoints.MapGroup("/games").WithParameterValidation(); // 直接依赖注入 group.MapGet("/", (IGamesRepository repository) => repository.GetAll()); group.MapGet("/{id}", (IGamesRepository repository,int id) => { Game? game = repository.Get(id); if (game is null) { return Results.NotFound(); } return Results.Ok(game); }).WithName(GetGameEndpointName); group.MapPut("/{id}", (IGamesRepository repository,int id, Game updatedGame) => { Game? existingGame = repository.Get(id); if (existingGame is null) { return Results.NotFound(); } existingGame.Name = updatedGame.Name; existingGame.Genre = updatedGame.Genre; existingGame.Price = updatedGame.Price; existingGame.ReleaseDate = updatedGame.ReleaseDate; existingGame.ImgUri = updatedGame.ImgUri; repository.Update(existingGame); return Results.NoContent(); }); group.MapDelete("/{id}", (IGamesRepository repository,int id) => { Game? game = repository.Get (id); if (game is not null) { repository.Delete(id); } return Results.NoContent(); }); return group; } }
对比
手动实例化
InMemGamesRepository repository = new(); group.MapGet("/", () => repository.GetAll());
依赖注入
依赖注入:
group.MapGet("/", (IGamesRepository repository) => repository.GetAll());
注册服务:
只有在builder中注册了服务,上面的接口在访问的时候才会自动帮你实例化.
var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton<IGamesRepository, InMemGamesRepository>(); // builder.Services.AddScoped<IGamesRepository, InMemGamesRepository>();
"""
"""#dotnetzz_dotnet_接口的扩展方法.md
接口的扩展方法
定义
当我们在C#中定义接口时,有时候我们希望为接口添加一些额外的方法,但是我们又不想修改接口本身。这时,接口的扩展方法就派上用场了。
接口的扩展方法允许我们在不改变接口定义的情况下,为接口添加新的方法。这些方法可以像实例方法一样调用,但实际上它们是静态方法。
例子
假设我们有一个接口 IVehicle
,表示交通工具。我们想要为这个接口添加一个新的方法,计算交通工具行驶的英尺数。我们可以使用接口的扩展方法来实现这个功能。
public interface IVehicle { int MilesDriven { get; set; } } public static class Extensions { // 这是一个接口的扩展方法 public static int FeetDriven(this IVehicle vehicle) { // 假设1英里等于5028英尺 return vehicle.MilesDriven * 5028; } } class Program { static void Main() { // 创建一个实现了 IVehicle 接口的类 var car = new Car { MilesDriven = 100 }; // 调用扩展方法 int feet = car.FeetDriven(); Console.WriteLine($"Car has driven {feet} feet."); } } public class Car : IVehicle { public int MilesDriven { get; set; } }
在上面的代码中,我们定义了一个接口 IVehicle
,表示交通工具。然后,我们创建了一个扩展方法 FeetDriven
,它可以在任何实现了 IVehicle
接口的类上调用。在 Main
方法中,我们创建了一个 Car
类的实例,并调用了扩展方法来计算行驶的英尺数。
总之,接口的扩展方法允许我们为接口添加新的方法,而无需修改接口本身。这对于在不破坏现有代码的情况下扩展接口功能非常有用。
this关键字
在C#中,this
关键字用于引用当前对象的实例。在接口的扩展方法中,this
关键字表示该方法是一个扩展方法,并且可以在实现了该接口的类的实例上调用。
让我详细解释一下:
- 当我们定义一个接口的扩展方法时,我们需要在静态类中创建一个静态方法。这个方法的第一个参数必须使用
this
关键字,指示我们要扩展的类型。 - 在调用这个扩展方法时,我们可以像调用实例方法一样使用它,但实际上它是一个静态方法。
this
关键字告诉编译器将当前实例作为第一个参数传递给这个方法。
例如,如果我们有一个接口 IVehicle
表示交通工具,我们可以为它添加一个扩展方法来计算行驶的英尺数。在这个方法中,this IVehicle vehicle
表示我们要在实现了 IVehicle
接口的类的实例上调用这个方法。
"""
"""#dotnetzz_dotnet_eftool指定文件夹.md
ef core 生成迁移文件时,如何指定文件夹
dotnet ef migrations add InitialCreate --output-dir Data/Migrations dotnet ef database update
"""
"""#dotnetzz_dotnet_的依赖注入.md
原先的模式
GamesEndpoints.cs
public static class GamesEndpoints { public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints) { // 自动创建一个实例,然后使用 InMemGamesRepository repository = new(); var group = endpoints.MapGroup("/games").WithParameterValidation(); group.MapGet("/", () => repository.GetAll()); return group; } }
InMemGamesRepository.cs
using GameStore.Api.Entities; namespace GameStore.Api.Repositoriesa; public class InMemGamesRepository { private readonly List<Game> games = new() { new Game(){ Id = 1, Name="Street Fighter II", Genre ="Fighting", Price = 19.99M, ReleaseDate = new DateTime(1991,2,1), ImgUri = "https://palcehold.co/100" }, new Game(){ Id = 2, Name="FIFA 23", Genre ="Sports", Price = 29.99M, ReleaseDate = new DateTime(2022,2,1), ImgUri = "https://palcehold.co/100" }, }; public IEnumerable<Game> GetAll() { return games; } public Game? Get(int id) { return games.Find(game => game.Id == id); } public void Create(Game game) { game.Id = games.Max(game => game.Id) + 1; games.Add(game); } public void Update(Game updatedGame) { var index = games.FindIndex(game => game.Id == updatedGame.Id); games[index] = updatedGame; } public void Delete(int id) { var index = games.FindIndex(game => game.Id == id); games.RemoveAt(index); } }
现在的模式
GamesEndpoints.cs
using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata; using GameStore.Api.Entities; using GameStore.Api.Repositoriesa; namespace GameStore.Api.Endpoints; public static class GamesEndpoints { const string GetGameEndpointName = "GetGame"; public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints) { var group = endpoints.MapGroup("/games").WithParameterValidation(); // 直接依赖注入 group.MapGet("/", (IGamesRepository repository) => repository.GetAll()); group.MapGet("/{id}", (IGamesRepository repository,int id) => { Game? game = repository.Get(id); if (game is null) { return Results.NotFound(); } return Results.Ok(game); }).WithName(GetGameEndpointName); group.MapPut("/{id}", (IGamesRepository repository,int id, Game updatedGame) => { Game? existingGame = repository.Get(id); if (existingGame is null) { return Results.NotFound(); } existingGame.Name = updatedGame.Name; existingGame.Genre = updatedGame.Genre; existingGame.Price = updatedGame.Price; existingGame.ReleaseDate = updatedGame.ReleaseDate; existingGame.ImgUri = updatedGame.ImgUri; repository.Update(existingGame); return Results.NoContent(); }); group.MapDelete("/{id}", (IGamesRepository repository,int id) => { Game? game = repository.Get (id); if (game is not null) { repository.Delete(id); } return Results.NoContent(); }); return group; } }
对比
手动实例化
InMemGamesRepository repository = new(); group.MapGet("/", () => repository.GetAll());
依赖注入
依赖注入:
group.MapGet("/", (IGamesRepository repository) => repository.GetAll());
注册服务:
只有在builder中注册了服务,上面的接口在访问的时候才会自动帮你实例化.
var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton<IGamesRepository, InMemGamesRepository>(); // builder.Services.AddScoped<IGamesRepository, InMemGamesRepository>();
"""
"""#dotnetzz_dotnet_接口的扩展方法.md
接口的扩展方法
定义
当我们在C#中定义接口时,有时候我们希望为接口添加一些额外的方法,但是我们又不想修改接口本身。这时,接口的扩展方法就派上用场了。
接口的扩展方法允许我们在不改变接口定义的情况下,为接口添加新的方法。这些方法可以像实例方法一样调用,但实际上它们是静态方法。
例子
假设我们有一个接口 IVehicle
,表示交通工具。我们想要为这个接口添加一个新的方法,计算交通工具行驶的英尺数。我们可以使用接口的扩展方法来实现这个功能。
public interface IVehicle { int MilesDriven { get; set; } } public static class Extensions { // 这是一个接口的扩展方法 public static int FeetDriven(this IVehicle vehicle) { // 假设1英里等于5028英尺 return vehicle.MilesDriven * 5028; } } class Program { static void Main() { // 创建一个实现了 IVehicle 接口的类 var car = new Car { MilesDriven = 100 }; // 调用扩展方法 int feet = car.FeetDriven(); Console.WriteLine($"Car has driven {feet} feet."); } } public class Car : IVehicle { public int MilesDriven { get; set; } }
在上面的代码中,我们定义了一个接口 IVehicle
,表示交通工具。然后,我们创建了一个扩展方法 FeetDriven
,它可以在任何实现了 IVehicle
接口的类上调用。在 Main
方法中,我们创建了一个 Car
类的实例,并调用了扩展方法来计算行驶的英尺数。
总之,接口的扩展方法允许我们为接口添加新的方法,而无需修改接口本身。这对于在不破坏现有代码的情况下扩展接口功能非常有用。
this关键字
在C#中,this
关键字用于引用当前对象的实例。在接口的扩展方法中,this
关键字表示该方法是一个扩展方法,并且可以在实现了该接口的类的实例上调用。
让我详细解释一下:
- 当我们定义一个接口的扩展方法时,我们需要在静态类中创建一个静态方法。这个方法的第一个参数必须使用
this
关键字,指示我们要扩展的类型。 - 在调用这个扩展方法时,我们可以像调用实例方法一样使用它,但实际上它是一个静态方法。
this
关键字告诉编译器将当前实例作为第一个参数传递给这个方法。
例如,如果我们有一个接口 IVehicle
表示交通工具,我们可以为它添加一个扩展方法来计算行驶的英尺数。在这个方法中,this IVehicle vehicle
表示我们要在实现了 IVehicle
接口的类的实例上调用这个方法。
"""
"""#dotnetzz_dotnet_eftool指定文件夹.md
ef core 生成迁移文件时,如何指定文件夹
dotnet ef migrations add InitialCreate --output-dir Data/Migrations dotnet ef database update
"""
"""#otherzz_other_vscode插件restclient的使用.md
vscode插件中restclient插件的使用
1.讲下面的文件保存 xxx.http 的格式的文件
### get GET http://localhost:5090/games HTTP/1.1 ### get by id GET http://localhost:5090/games/1 HTTP/1.1 ### post POST http://localhost:5090/games HTTP/1.1 content-type: application/json { "name": "Hun Dou Luo2222222", "genre": "Fighting", "price": 19.99, "releaseDate": "1992-02-01T00:00:00", "imageUri": "https://palcehold.co/100" } ### post missing name POST http://localhost:5090/games HTTP/1.1 content-type: application/json { "genre": "Fighting", "price": 19.99, "releaseDate": "1992-02-01T00:00:00", "imageUri": "https://palcehold.co/100" }
"""
"""#pythonzz_python_正则表达式.md
正则表达式在线测试网站
regexr
分组匹配
import re name = "#==other==zz_other_vscode插件restclient的使用.md" pattern = re.compile(r'#==(.{1,10})==(.+).md') res =pattern.match(name) if res: print(res.groups()) # => ('other', 'zz_other_vscode插件restclient的使用') print(res.groups()[0])# => other print(res.groups()[1])# => zz_other_vscode插件restclient的使用
正则表达式中各个函数的区别
re.match
- re.match(pattern, string):这个函数用于检查字符串的开头是否匹配给定的模式,如果匹配,返回一个匹配对象,否则返回None。这个函数只在字符串的开头进行匹配,不会在字符串的其他位置查找模式。例如:
import re result = re.match(r"hello", "hello world") print(result) # <re.Match object; span=(0, 5), match='hello'> result = re.match(r"world", "hello world") print(result) # None
re.search
- re.search(pattern, string):这个函数用于在字符串中查找给定的模式的第一个匹配,如果找到,返回一个匹配对象,否则返回None。这个函数会在字符串的任何位置进行匹配,不仅仅是开头。例如:
import re result = re.search(r"hello", "hello world") print(result) # <re.Match object; span=(0, 5), match='hello'> result = re.search(r"world", "hello world") print(result) # <re.Match object; span=(6, 11), match='world'>
re.findall
- re.findall(pattern, string):这个函数用于在字符串中查找给定的模式的所有匹配,返回一个包含所有匹配的字符串的列表,如果没有找到匹配,返回一个空列表。这个函数会在字符串的任何位置进行匹配,不会停止在第一个匹配。例如:
import re result = re.findall(r"hello", "hello world hello python") print(result) # ['hello', 'hello'] result = re.findall(r"world", "hello world hello python") print(result) # ['world']
re.finditer
- re.finditer(pattern, string):这个函数用于在字符串中查找给定的模式的所有匹配,返回一个包含所有匹配对象的迭代器,如果没有找到匹配,返回一个空的迭代器。这个函数会在字符串的任何位置进行匹配,不会停止在第一个匹配。这个函数与re.findall的区别是,它返回的是匹配对象,而不是字符串,这样可以获取更多的匹配信息,如位置,分组等。例如:
import re result = re.finditer(r"hello", "hello world hello python") for match in result: print(match) # <re.Match object; span=(0, 5), match='hello'> # <re.Match object; span=(12, 17), match='hello'> result = re.finditer(r"world", "hello world hello python") for match in result: print(match) # <re.Match object; span=(6, 11), match='world'>
re.sub
- re.sub(pattern, repl, string):这个函数用于在字符串中替换给定的模式的所有匹配,返回一个新的字符串,其中所有的匹配都被repl替换,如果没有找到匹配,返回原始字符串。repl可以是一个字符串,也可以是一个函数,用于根据匹配对象生成替换的字符串。例如:
import re result = re.sub(r"hello", "hi", "hello world hello python") print(result) # hi world hi python result = re.sub(r"(\w+) (\w+)", r"\2 \1", "hello world hello python") print(result) # world hello python hello
re.split
- re.split(pattern, string):这个函数用于用给定的模式作为分隔符,将字符串分割成多个子字符串,返回一个包含所有子字符串的列表,如果没有找到匹配,返回一个只包含原始字符串的列表。例如:
import re result = re.split(r"\s", "hello world hello python") print(result) # ['hello', 'world', 'hello', 'python'] result = re.split(r"o", "hello world hello python") print(result) # ['hell', ' w', 'rld hell', ' pyth', 'n']
"""
"""#dotnetzz_dotnet_的依赖注入.md
原先的模式
GamesEndpoints.cs
public static class GamesEndpoints { public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints) { // 自动创建一个实例,然后使用 InMemGamesRepository repository = new(); var group = endpoints.MapGroup("/games").WithParameterValidation(); group.MapGet("/", () => repository.GetAll()); return group; } }
InMemGamesRepository.cs
using GameStore.Api.Entities; namespace GameStore.Api.Repositoriesa; public class InMemGamesRepository { private readonly List<Game> games = new() { new Game(){ Id = 1, Name="Street Fighter II", Genre ="Fighting", Price = 19.99M, ReleaseDate = new DateTime(1991,2,1), ImgUri = "https://palcehold.co/100" }, new Game(){ Id = 2, Name="FIFA 23", Genre ="Sports", Price = 29.99M, ReleaseDate = new DateTime(2022,2,1), ImgUri = "https://palcehold.co/100" }, }; public IEnumerable<Game> GetAll() { return games; } public Game? Get(int id) { return games.Find(game => game.Id == id); } public void Create(Game game) { game.Id = games.Max(game => game.Id) + 1; games.Add(game); } public void Update(Game updatedGame) { var index = games.FindIndex(game => game.Id == updatedGame.Id); games[index] = updatedGame; } public void Delete(int id) { var index = games.FindIndex(game => game.Id == id); games.RemoveAt(index); } }
现在的模式
GamesEndpoints.cs
using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata; using GameStore.Api.Entities; using GameStore.Api.Repositoriesa; namespace GameStore.Api.Endpoints; public static class GamesEndpoints { const string GetGameEndpointName = "GetGame"; public static RouteGroupBuilder MapGamesEndpoints(this IEndpointRouteBuilder endpoints) { var group = endpoints.MapGroup("/games").WithParameterValidation(); // 直接依赖注入 group.MapGet("/", (IGamesRepository repository) => repository.GetAll()); group.MapGet("/{id}", (IGamesRepository repository,int id) => { Game? game = repository.Get(id); if (game is null) { return Results.NotFound(); } return Results.Ok(game); }).WithName(GetGameEndpointName); group.MapPut("/{id}", (IGamesRepository repository,int id, Game updatedGame) => { Game? existingGame = repository.Get(id); if (existingGame is null) { return Results.NotFound(); } existingGame.Name = updatedGame.Name; existingGame.Genre = updatedGame.Genre; existingGame.Price = updatedGame.Price; existingGame.ReleaseDate = updatedGame.ReleaseDate; existingGame.ImgUri = updatedGame.ImgUri; repository.Update(existingGame); return Results.NoContent(); }); group.MapDelete("/{id}", (IGamesRepository repository,int id) => { Game? game = repository.Get (id); if (game is not null) { repository.Delete(id); } return Results.NoContent(); }); return group; } }
对比
手动实例化
InMemGamesRepository repository = new(); group.MapGet("/", () => repository.GetAll());
依赖注入
依赖注入:
group.MapGet("/", (IGamesRepository repository) => repository.GetAll());
注册服务:
只有在builder中注册了服务,上面的接口在访问的时候才会自动帮你实例化.
var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton<IGamesRepository, InMemGamesRepository>(); // builder.Services.AddScoped<IGamesRepository, InMemGamesRepository>();
"""
"""#dotnetzz_dotnet_接口的扩展方法.md
接口的扩展方法
定义
当我们在C#中定义接口时,有时候我们希望为接口添加一些额外的方法,但是我们又不想修改接口本身。这时,接口的扩展方法就派上用场了。
接口的扩展方法允许我们在不改变接口定义的情况下,为接口添加新的方法。这些方法可以像实例方法一样调用,但实际上它们是静态方法。
例子
假设我们有一个接口 IVehicle
,表示交通工具。我们想要为这个接口添加一个新的方法,计算交通工具行驶的英尺数。我们可以使用接口的扩展方法来实现这个功能。
public interface IVehicle { int MilesDriven { get; set; } } public static class Extensions { // 这是一个接口的扩展方法 public static int FeetDriven(this IVehicle vehicle) { // 假设1英里等于5028英尺 return vehicle.MilesDriven * 5028; } } class Program { static void Main() { // 创建一个实现了 IVehicle 接口的类 var car = new Car { MilesDriven = 100 }; // 调用扩展方法 int feet = car.FeetDriven(); Console.WriteLine($"Car has driven {feet} feet."); } } public class Car : IVehicle { public int MilesDriven { get; set; } }
在上面的代码中,我们定义了一个接口 IVehicle
,表示交通工具。然后,我们创建了一个扩展方法 FeetDriven
,它可以在任何实现了 IVehicle
接口的类上调用。在 Main
方法中,我们创建了一个 Car
类的实例,并调用了扩展方法来计算行驶的英尺数。
总之,接口的扩展方法允许我们为接口添加新的方法,而无需修改接口本身。这对于在不破坏现有代码的情况下扩展接口功能非常有用。
this关键字
在C#中,this
关键字用于引用当前对象的实例。在接口的扩展方法中,this
关键字表示该方法是一个扩展方法,并且可以在实现了该接口的类的实例上调用。
让我详细解释一下:
- 当我们定义一个接口的扩展方法时,我们需要在静态类中创建一个静态方法。这个方法的第一个参数必须使用
this
关键字,指示我们要扩展的类型。 - 在调用这个扩展方法时,我们可以像调用实例方法一样使用它,但实际上它是一个静态方法。
this
关键字告诉编译器将当前实例作为第一个参数传递给这个方法。
例如,如果我们有一个接口 IVehicle
表示交通工具,我们可以为它添加一个扩展方法来计算行驶的英尺数。在这个方法中,this IVehicle vehicle
表示我们要在实现了 IVehicle
接口的类的实例上调用这个方法。
"""
"""#dotnetzz_dotnet_eftool指定文件夹.md
ef core 生成迁移文件时,如何指定文件夹
dotnet ef migrations add InitialCreate --output-dir Data/Migrations dotnet ef database update
"""
"""#otherzz_other_vscode插件restclient的使用.md
vscode插件中restclient插件的使用
1.讲下面的文件保存 xxx.http 的格式的文件
### get GET http://localhost:5090/games HTTP/1.1 ### get by id GET http://localhost:5090/games/1 HTTP/1.1 ### post POST http://localhost:5090/games HTTP/1.1 content-type: application/json { "name": "Hun Dou Luo2222222", "genre": "Fighting", "price": 19.99, "releaseDate": "1992-02-01T00:00:00", "imageUri": "https://palcehold.co/100" } ### post missing name POST http://localhost:5090/games HTTP/1.1 content-type: application/json { "genre": "Fighting", "price": 19.99, "releaseDate": "1992-02-01T00:00:00", "imageUri": "https://palcehold.co/100" }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战