commit f01a18a15a8a03e3fc8d6462e41f230e5397c76f Author: Dylan R. E. Moonfire Date: Thu Jan 18 16:16:01 2018 -0600 Initial commit. diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c90eff1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# EditorConfig is awesome: http://EditorConfig.org +# +# https://visualstudiogallery.msdn.microsoft.com/c8bccfe2-650c-4b42-bc5c-845e21f96328 +# Or install via Extensions inside Visual Studio. + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8-bom +indent_style = space +tab_width = 4 +trim_trailing_whitespace = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c4efe2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,261 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..02b160f --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Moonfire Games + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/MfGames.Locking.sln b/MfGames.Locking.sln new file mode 100644 index 0000000..264106d --- /dev/null +++ b/MfGames.Locking.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2024 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Locking", "MfGames.Locking\MfGames.Locking.csproj", "{51E00BEF-AAF1-4D45-BF82-5DCD7D5EA7FC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {51E00BEF-AAF1-4D45-BF82-5DCD7D5EA7FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51E00BEF-AAF1-4D45-BF82-5DCD7D5EA7FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51E00BEF-AAF1-4D45-BF82-5DCD7D5EA7FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51E00BEF-AAF1-4D45-BF82-5DCD7D5EA7FC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FED5BE58-8CEB-48E6-82E0-0B80035F4AEA} + EndGlobalSection +EndGlobal diff --git a/MfGames.Locking.sln.DotSettings b/MfGames.Locking.sln.DotSettings new file mode 100644 index 0000000..c62cd45 --- /dev/null +++ b/MfGames.Locking.sln.DotSettings @@ -0,0 +1,1303 @@ + + + + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + HINT + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + DoHide + HINT + <?xml version="1.0" encoding="utf-16"?><Profile name="Full WEI Cleanup"><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_BOTH</BehavourStyle><LocalVariableStyle>IMPLICIT_WHEN_INITIALIZER_HAS_TYPE</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName>Namespaces</RegionName></CSOptimizeUsings><CSUseAutoProperty>True</CSUseAutoProperty><CSArrangeQualifiers>True</CSArrangeQualifiers><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="True" ArrangeBraces="False" ArrangeAttributes="True" ArrangeArgumentsStyle="True" ArrangeCodeBodyStyle="True" ArrangeVarStyle="True" /><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSUpdateFileHeader>True</CSUpdateFileHeader><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><CSharpFormatDocComments>True</CSharpFormatDocComments><CSReorderTypeMembers>True</CSReorderTypeMembers><JsInsertSemicolon>True</JsInsertSemicolon><HtmlReformatCode>True</HtmlReformatCode></Profile> + <?xml version="1.0" encoding="utf-16"?><Profile name="Remove Redundant Qualifiers"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSUseAutoProperty>False</CSUseAutoProperty><CSMakeFieldReadonly>False</CSMakeFieldReadonly><CSUseVar><BehavourStyle>DISABLED</BehavourStyle><LocalVariableStyle>IMPLICIT_WHEN_INITIALIZER_HAS_TYPE</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSUpdateFileHeader>False</CSUpdateFileHeader><VBOptimizeImports>False</VBOptimizeImports><VBShortenReferences>False</VBShortenReferences><CSOptimizeUsings><OptimizeUsings>False</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName /></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><VBReformatCode>False</VBReformatCode><CSReformatCode>False</CSReformatCode><CSReorderTypeMembers>False</CSReorderTypeMembers></Profile> + Full Cleanup + Full WEI Cleanup + OPTIMAL_FILL + True + False + True + Required + Required + Required + Required + 15 + OPTIMAL_FILL + False + False + False + False + False + False + False + False + NEXT_LINE + 1 + 1 + 1 + 1 + 1 + 1 + + 1 + NEXT_LINE + SEPARATE + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + ALWAYS_ADD + True + Tab + NEXT_LINE + 1 + 1 + True + NEVER + NEVER + False + False + NEVER + False + False + True + False + True + + False + True + False + + True + True + CHOP_IF_LONG + True + True + True + CHOP_IF_LONG + CHOP_IF_LONG + OPTIMAL_FILL + OPTIMAL_FILL + OPTIMAL_FILL + + Tab + True + 1 + 1 + True + 1 + False + False + True + True + True + CHOP_IF_LONG + OPTIMAL_FILL + OPTIMAL_FILL + OPTIMAL_FILL + OPTIMAL_FILL + ZeroIndent + ZeroIndent + OPTIMAL_FILL + <?xml version="1.0" encoding="utf-16"?> +<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> + <TypePattern DisplayName="StyleCop Layout" RemoveRegions="All"> + <TypePattern.Match> + <Or> + <Kind Is="Class" /> + <Kind Is="Struct" /> + <Kind Is="Interface" /> + </Or> + </TypePattern.Match> + <Entry DisplayName="Constants"> + <Entry.Match> + <Kind Is="Constant" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Static fields"> + <Entry.Match> + <And> + <Kind Is="Field" /> + <Static /> + </And> + </Entry.Match> + <Entry.SortBy> + <Kind Order="Constant Field" /> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Readonly /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Fields"> + <Entry.Match> + <Kind Is="Field" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Readonly /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Constructors and destructors" Priority="200"> + <Entry.Match> + <Or> + <Kind Is="Constructor" /> + <Kind Is="Destructor" /> + </Or> + </Entry.Match> + <Entry.SortBy> + <Static /> + <Kind Order="Constructor Destructor" /> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Delegates"> + <Entry.Match> + <Kind Is="Delegate" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Public events"> + <Entry.Match> + <And> + <Kind Is="Event" /> + <Access Is="Public" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Interface events"> + <Entry.Match> + <And> + <Kind Is="Event" /> + <ImplementsInterface /> + </And> + </Entry.Match> + <Entry.SortBy> + <ImplementsInterface Immediate="True" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Other events"> + <Entry.Match> + <Kind Is="Event" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Enums"> + <Entry.Match> + <Kind Is="Enum" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Interfaces"> + <Entry.Match> + <Kind Is="Interface" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Public properties"> + <Entry.Match> + <And> + <Kind Is="Property" /> + <Access Is="Public" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Interface properties"> + <Entry.Match> + <And> + <Kind Is="Property" /> + <ImplementsInterface /> + </And> + </Entry.Match> + <Entry.SortBy> + <ImplementsInterface Immediate="True" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Other properties"> + <Entry.Match> + <Kind Is="Property" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Public indexers" Priority="1000"> + <Entry.Match> + <And> + <Kind Is="Indexer" /> + <Access Is="Public" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Interface indexers" Priority="1000"> + <Entry.Match> + <And> + <Kind Is="Indexer" /> + <ImplementsInterface /> + </And> + </Entry.Match> + <Entry.SortBy> + <ImplementsInterface Immediate="True" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Other indexers" Priority="1000"> + <Entry.Match> + <Kind Is="Indexer" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Public methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Access Is="Public" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Interface methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <ImplementsInterface /> + </And> + </Entry.Match> + <Entry.SortBy> + <ImplementsInterface Immediate="True" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Other methods"> + <Entry.Match> + <Kind Is="Method" /> + </Entry.Match> + <Entry.SortBy> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Static /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Operators"> + <Entry.Match> + <Kind Is="Operator" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Nested structs" Priority="600"> + <Entry.Match> + <Kind Is="Struct" /> + </Entry.Match> + <Entry.SortBy> + <Static /> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="Nested classes" Priority="700"> + <Entry.Match> + <Kind Is="Class" /> + </Entry.Match> + <Entry.SortBy> + <Static /> + <Access Order="Public Internal ProtectedInternal Protected Private" /> + <Name /> + </Entry.SortBy> + </Entry> + <Entry DisplayName="All other members" /> + </TypePattern> +</Patterns> + <?xml version="1.0" encoding="utf-8" ?> + +<!-- +I. Overall + +I.1 Each pattern can have <Match>....</Match> element. For the given type declaration, the pattern with the match, evaluated to 'true' with the largest weight, will be used +I.2 Each pattern consists of the sequence of <Entry>...</Entry> elements. Type member declarations are distributed between entries +I.3 If pattern has RemoveAllRegions="true" attribute, then all regions will be cleared prior to reordering. Otherwise, only auto-generated regions will be cleared +I.4 The contents of each entry is sorted by given keys (First key is primary, next key is secondary, etc). Then the declarations are grouped and en-regioned by given property + +II. Available match operands + +Each operand may have Weight="..." attribute. This weight will be added to the match weight if the operand is evaluated to 'true'. +The default weight is 1 + +II.1 Boolean functions: +II.1.1 <And>....</And> +II.1.2 <Or>....</Or> +II.1.3 <Not>....</Not> + +II.2 Operands +II.2.1 <Kind Is="..."/>. Kinds are: class, struct, interface, enum, delegate, type, constructor, destructor, property, indexer, method, operator, field, constant, event, member +II.2.2 <Name Is="..." [IgnoreCase="true/false"] />. The 'Is' attribute contains regular expression +II.2.3 <HasAttribute CLRName="..." [Inherit="true/false"] />. The 'CLRName' attribute contains regular expression +II.2.4 <Access Is="..."/>. The 'Is' values are: public, protected, internal, protected internal, private +II.2.5 <Static/> +II.2.6 <Abstract/> +II.2.7 <Virtual/> +II.2.8 <Override/> +II.2.9 <Sealed/> +II.2.10 <Readonly/> +II.2.11 <ImplementsInterface CLRName="..."/>. The 'CLRName' attribute contains regular expression +II.2.12 <HandlesEvent /> +--> + +<Patterns xmlns="urn:shemas-jetbrains-com:member-reordering-patterns"> + + <!--Do not reorder COM interfaces--> + <Pattern> + <Match> + <And Weight="100"> + <Kind Is="interface"/> + <HasAttribute CLRName="System.Runtime.InteropServices.InterfaceTypeAttribute"/> + </And> + </Match> + </Pattern> + + <!--Default pattern--> + <Pattern> + + <!--public delegate--> + <Entry> + <Match> + <And Weight="100"> + <Access Is="public"/> + <Kind Is="delegate"/> + </And> + </Match> + <Sort> + <Name/> + </Sort> + <Group Region="Delegates"/> + </Entry> + + <!--public enum--> + <Entry> + <Match> + <And Weight="100"> + <Access Is="public"/> + <Kind Is="enum"/> + </And> + </Match> + <Sort> + <Name/> + </Sort> + <Group> + <Name Region="${Name} enum"/> + </Group> + </Entry> + + <!--fields and constants--> + <Entry> + <Match> + <Or> + <Kind Is="constant"/> + <Kind Is="field"/> + </Or> + </Match> + <Sort> + <Name/> + </Sort> + </Entry> + + <!--Constructors. Place static one first--> + <Entry> + <Match> + <Kind Is="constructor"/> + </Match> + <Sort> + <Static/> + </Sort> + </Entry> + + <!--properties, indexers--> + <Entry> + <Match> + <Or> + <Kind Is="property"/> + <Kind Is="indexer"/> + </Or> + </Match> + <Sort> + <Name/> + </Sort> + </Entry> + + <!--all other members--> + <Entry> + <Sort> + <Name/> + </Sort> + </Entry> + + <!--nested types--> + <Entry> + <Match> + <Kind Is="type"/> + </Match> + <Sort> + <Name/> + </Sort> + <Group> + <Name Region="Nested type: ${Name}"/> + </Group> + </Entry> + </Pattern> + +</Patterns> + + CustomLayout + True + False + UseExplicitType + UseVarWhenEvident + UseVarWhenEvident + <copyright file="$FILENAME$" company="Moonfire Games"> +Copyright (c) Moonfire Games. +This code is licensed under the MIT license. +See LICENSE.md in the source or https://opensource.org/licenses/MIT +</copyright> + + False + + + ATI + CUSIP + + + + + IO + IP + + + + + PDF + RPC + RPO + XML + On$event$ + exception + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + + + + + + + + $object$_On$event$ + exception + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="True" Prefix="m_" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="m_" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Private Events"><ElementKinds><Kind Name="EVENT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="m_" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private, Protected, ProtectedInternal, Internal" Description="Dual rules for readonly/constants"><ElementKinds><Kind Name="READONLY_FIELD" /><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB"><ExtraRule Prefix="m_" Suffix="" Style="AaBb" /></Policy></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Public" Description="Dual rules for public fields"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AA_BB" /></Policy></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Public" Description="Dual rules for public fields"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="AA_BB" /></Policy></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private, Protected, ProtectedInternal, Internal" Description="Dual rules for readonly/constants"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB"><ExtraRule Prefix="m_" Suffix="" Style="AaBb" /></Policy></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Private Events"><ElementKinds><Kind Name="EVENT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="m_" Suffix="" Style="AaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + LIVE_MONITOR + LIVE_MONITOR + DO_NOTHING + LIVE_MONITOR + LIVE_MONITOR + LIVE_MONITOR + LIVE_MONITOR + LIVE_MONITOR + LIVE_MONITOR + LIVE_MONITOR + LIVE_MONITOR + DO_NOTHING + LIVE_MONITOR + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + Always + False + tag + 10 + ( ) + 14 + 15 + #region(WEI) + 4 + 16 + + False + + using + False + 0 + NUnit Test + 1 + Class (WEI) + False + + 2 + 4 + 3 + True + True + Events + Imported 1/13/2012 + Create Thread-Safe Event + True + Event with Synchronous Invoke + True + public event $EventHandler$<$EventArgs$> $EventName$ +{ + add + { + lock(m_EventLock) + { + m_$PrivateEventVariable$Event += value; + } + } + remove + { + lock (m_EventLock) + { + m_$PrivateEventVariable$Event -= value; + } + } +} +$END$ + +private event $EventHandler$<$EventArgs$> m_$PrivateEventVariable$Event; + +/// <summary> +/// Raises the $EventName$ event synchronously. +/// </summary> +/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param> +private void Raise$EventName$($EventArgs$ args) +{ + $EventHandler$<$EventArgs$> handler = m_$PrivateEventVariable$Event; + if (handler != null) + { + handler(this, args); + } +} + + True + 1 + True + 0 + True + 2 + True + capitalize(EventName) + 3 + True + 2.0 + InCSharpTypeMember + True + True + cs + Test + True + NUnit Test + True + True + #region Namespaces + +using System; + +using NUnit.Framework; + +#endregion + +namespace $NameSpace$ +{ + [TestFixture] + public class $TestClass$ + { + #region Public Methods + + #region Test Administration + + [TestFixtureSetUp] + public void TestFixtureSetup() + { + } + + [TestFixtureTearDown] + public void TestFixtureTeardown() + { + } + + [SetUp] + public void Setup() + { + } + + [TearDown] + public void Teardown() + { + } + + #endregion Test Administration + + #region Test Methods + + #endregion Test Methods + + #endregion Public Methods + + #region Private Fields + + #endregion Private Fields + + #region Private Methods + + #endregion Private Methods + } +} + True + 0 + True + 1 + True + InCSharpProjectFile + True + True + IDisposable Implementation for a Base Class + True + IDisposable Base Class + True + #region IDisposable Implementation + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + // NOTE: Leave out the finalizer altogether if this class doesn't own + // unmanaged resources itself, but leave the other methods + // exactly as they are. + + ~$ClassName$() + { + Dispose(false); + } + + + protected virtual void Dispose(bool disposing) + { + // Even if we don't have a finalizer, we need to check the disposing argument. + // It might still be false if we're being finalized due to the fact that a derived + // class introduced a finalizer. + + if (disposing) + { + // free managed resources + } + + // free native resources if there are any. + } + +#endregion IDisposable Implementation + + True + 0 + True + 2.0 + InCSharpTypeMember + True + True + Imported 1/13/2012 + WEI Standard + cs + Class + False + WEI Class + True + Class (WEI) + True + #region Namespaces + +using System; + +#endregion Namespaces + +namespace $NAMESPACE$ +{ + + public class $CLASS$ + { + #region Constructors + public $CLASS$() + { + $END$ + } + + #endregion Constructors + + #region Public Properties + #endregion Public Properties + + #region Public Methods + #endregion Public Methods + + #region Private Fields + #endregion Private Fields + + #region Private Methods + #endregion Private Methods + + } + +} + True + getFileNameWithoutExtension() + 0 + True + fileDefaultNamespace() + 1 + True + InCSharpProjectFile + True + True + Imported 1/13/2012 + Methods + Unit Test Method + True + Test Method + True + [Test] +[Category("")] +public void $MethodUnderTest$_$Scenario$_$ExpectedResult$() +{ + // Arrange +$END$ + + // Act + + // Assert +} + True + 2 + True + 0 + True + 1 + True + 2.0 + InCSharpTypeMember + True + True + Imported 1/13/2012 + LLBLGen Templates + Insert a Using(DataAccessAdapter) + True + UDAA + True + using(DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ + $END$ +} + True + 2.0 + InCSharpStatement + True + True + ( ) + True + True + ($SELECTION$) + True + 2.0 + InCSharpExpression + True + True + Imported 1/13/2012 + LLBLGen Templates + Retrieve Collection with a Filter + True + FetchCollection + True + EntityCollection $ResultCollectionName$Collection = new EntityCollection(new $EntityType$EntityFactory()); +using(DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ +RelationPredicateBucket filterBucket = new RelationPredicateBucket(); +IPredicateExpression predicateExpression = new PredicateExpression(); +predicateExpression.Add(PredicateFactory.CompareValue($EntityType$FieldIndex.$FilterField$, ComparisonOperator.Equal, $FilterValue$)); +filterBucket.PredicateExpression.Add(predicateExpression); + +dataAccessAdapter.FetchEntityCollection($ResultCollectionName$Collection, filterBucket); +} +$END$ + True + 0 + True + complete() + 2 + True + 3 + True + decapitalize(EntityType) + 1 + True + 2.0 + InCSharpStatement + True + True + Calls the session server to validate a user + True + ValidateUser + True + SessionServerFactory.GetSessionServer().IsValid(requestorInformation.SessionId); + True + 2.0 + InCSharpStatement + True + True + Imported 1/13/2012 + LLBLGen Templates + Retrieve Single Entity with a Filter + True + FetchEntityWithFilter + True + EntityCollection $CollectionType$Collection = new EntityCollection(new $EntityType$EntityFactory()); +using(DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ +RelationPredicateBucket filterBucket = new RelationPredicateBucket(); +IPredicateExpression predicateExpression = new PredicateExpression(); +predicateExpression.Add(PredicateFactory.CompareValue($EntityType$FieldIndex.$FilterField$, ComparisonOperator.Equal, $FilterValue$)); +filterBucket.PredicateExpression.Add(predicateExpression); + +dataAccessAdapter.FetchEntityCollection($CollectionType$Collection, filterBucket); +} +$EntityType$Entity $EntityObject$ = null; +if ($CollectionType$Collection.Count > 0) +$EntityObject$ = ($EntityType$Entity)$CollectionType$Collection[0]; +$END$ + True + decapitalize(EntityType) + 1 + True + suggestVariableName() + 4 + True + 0 + True + complete() + 2 + True + 3 + True + 2.0 + InCSharpStatement + True + True + Events + Imported 1/13/2012 + Create a thread-safe event with an asynchronous raise method + True + Event with Asynchronous Invoke + True + public event $EventHandler$<$EventArgs$> $EventName$ +{ + add + { + lock(m_EventLock) + { + m_$PrivateEventVariable$Event += value; + } + } + remove + { + lock (m_EventLock) + { + m_$PrivateEventVariable$Event -= value; + } + } +} +$END$ + +private event $EventHandler$<$EventArgs$> m_$PrivateEventVariable$Event; + +/// <summary> +/// Raises the $EventName$ event Asynchronously. +/// </summary> +/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param> +private void Raise$EventName$Async($EventArgs$ args) +{ + Delegate[] subscribers = null; + lock (m_EventLock) + { + if (m_$PrivateEventVariable$Event != null) + { + subscribers = m_$PrivateEventVariable$Event.GetInvocationList(); + } + } + + if (subscribers != null) + { + foreach ($EventHandler$ subscriber in subscribers) + { + subscriber.BeginInvoke(this, args, null, null); + } + } +} + + True + 1 + True + 0 + True + 2 + True + capitalize(EventName) + 3 + True + 2.0 + InCSharpTypeMember + True + True + Imported 1/13/2012 + LLBLGen Templates + Fetch an entity with a joined relation + True + FetchEntityWithJoin + True + EntityCollection $CollectionType$Collection = new EntityCollection(new $EntityType1$EntityFactory()); +using (DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ + RelationPredicateBucket filterBucket = new RelationPredicateBucket(); + + // Filter The First Entity on a Field Value + IPredicateExpression predicateExpression = new PredicateExpression(); + predicateExpression.Add(PredicateFactory.CompareValue($EntityType1$FieldIndex.$FilterField1$, ComparisonOperator.Equal, $FilterValue1$)); + filterBucket.PredicateExpression.Add(predicateExpression); + + // Add the Join Relation + filterBucket.Relations.Add($EntityType1$Entity.Relations.$EntityRelationship$); + + // Filter The Second Entity on a Field Value + IPredicateExpression predicateExpression$EntityType2$ = new PredicateExpression(); + predicateExpression$EntityType2$.Add(PredicateFactory.CompareValue($EntityType2$FieldIndex.$FilterField2$, ComparisonOperator.Equal, $FilterValue2$)); + filterBucket.PredicateExpression.Add(predicateExpressionIdentifier); + + // Prefetch Joined Entity + IPrefetchPath2 prefetchPath = new PrefetchPath2((int)EntityType.$EntityType1$Entity); + prefetchPath.Add($EntityType1$Entity.PrefetchPath$EntityType2$, 0, predicateExpression$EntityType2$, new $EntityType2$EntityFactory()); + + dataAccessAdapter.FetchEntityCollection($CollectionType$Collection, filterBucket, prefetchPath); +} + +$EntityType1$Entity $EntityObject$; +if ($CollectionType$Collection.Count > 0) +{ + $EntityObject$ = ($EntityType1$Entity)$CollectionType$Collection[0]; + // Use the values in $EntityObject$ and the related entity $EntityType2$ +} + + True + decapitalize(EntityType1) + 0 + True + suggestVariableName() + 8 + True + complete() + 4 + True + 1 + True + 5 + True + complete() + 2 + True + complete() + 6 + True + 3 + True + 7 + True + 2.0 + InCSharpStatement + True + True + Imported 1/13/2012 + WEI Standard + #region (WEI) + True + #region(WEI) + True + #region $RegionName$$END$ +$SELECTION$ +#endregion $RegionName$ + + True + 0 + True + 2.0 + InCSharpFile + True + True + Imported 1/13/2012 + LLBLGen Templates + Fetch selected columns from single Entity + True + FetchSelectedColumns + True + using(DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ + ResultsetFields resultsetFields = new ResultsetFields($NUMBEROFFIELDS$); + int fieldIndex = 0; + resultsetFields.DefineField($ENTITY_TYPE$Fields.$FIELD1$, fieldIndex++); + resultsetFields.DefineField($ENTITY_TYPE$Fields.$FIELD2$, fieldIndex++); + // Add more fields as needed. Number of added fields must match parameter in constructor for ResultSetFields + + DataTable resultSet = new DataTable(); + dataAccessAdapter.FetchTypedList(resultsetFields, resultSet, null, $DISTINCT_TRUE_FALSE$); +} +$END$ + + True + 4 + True + 1 + True + 2 + True + 3 + True + 0 + True + 2.0 + InCSharpStatement + True + True + Imported 1/13/2012 + LLBLGen Templates + Retrieve an Entity by its Primary Key + True + FetchEntity + True + $EntityType$Entity $EntityObject$ = new $EntityType$Entity($PrimaryKeyValue$); +bool found; +using(DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ +found = dataAccessAdapter.FetchEntity($EntityObject$); +} +$END$ + True + suggestVariableName() + 1 + True + 0 + True + 2 + True + 2.0 + InCSharpStatement + True + True + Imported 1/13/2012 + LLBLGen Templates + Delete an entity + True + DeleteEntity + True + $EntityType$Entity $EntityObject$ = new $EntityType$Entity($PrimaryKeyValue$); +bool found; +using(DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ +found = dataAccessAdapter.DeleteEntity($EntityObject$); +} +$END$ + True + 1 + True + 0 + True + 2 + True + 2.0 + InCSharpStatement + True + True + Imported 1/13/2012 + LLBLGen Templates + Insert an Entity with LLBLGen + True + InsertEntity + True + $EntityType$Entity $EntityObject$ = new $EntityType$Entity(); +//$EntityObject$.fieldName1 = fieldValue1; + +using(DataAccessAdapter dataAccessAdapter = new DataAccessAdapter(ConnectionString.GetString("connString"), true)) +{ + dataAccessAdapter.SaveEntity($EntityObject$); + // newIdentityKey = $EntityObject$.IdentityKeyField; +} + + True + suggestVariableName() + 1 + True + 0 + True + 2.0 + InCSharpStatement \ No newline at end of file diff --git a/MfGames.Locking/MfGames.Locking.csproj b/MfGames.Locking/MfGames.Locking.csproj new file mode 100644 index 0000000..c3a4a82 --- /dev/null +++ b/MfGames.Locking/MfGames.Locking.csproj @@ -0,0 +1,39 @@ + + + + net452;net461;netstandard1.6;netstandard2.0;netcoreapp2.0 + MfGames.Locking + 5.0.0 + Dylan R. E. Moonfire + Various locking patterns for multi-threaded code. + false + Copyright (c) Moonfire Games. MIT license. + lock; locking + https://opensource.org/licenses/MIT + + + + bin\Debug\netcoreapp2.0\MfGames.Locking.xml + Off + + + + + + + + + + + + + + + + + all + compile; build; native; contentfiles; analyzers + + + + diff --git a/MfGames.Locking/NestableReadLock.cs b/MfGames.Locking/NestableReadLock.cs new file mode 100644 index 0000000..915c5f9 --- /dev/null +++ b/MfGames.Locking/NestableReadLock.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + using System; + using System.Threading; + + /// + /// Defines a ReaderWriterLockSlim read-only lock. + /// + public class NestableReadLock : IDisposable + { + private readonly bool lockAcquired; + + private readonly ReaderWriterLockSlim readerWriterLockSlim; + + /// + /// Initializes a new instance of the class. + /// + /// The reader writer lock slim. + public NestableReadLock(ReaderWriterLockSlim readerWriterLockSlim) + { + // Keep track of the lock since we'll need it to release the lock. + this.readerWriterLockSlim = readerWriterLockSlim; + + // If we already have a read or write lock, we don't do anything. + if (readerWriterLockSlim.IsReadLockHeld + || readerWriterLockSlim.IsUpgradeableReadLockHeld + || readerWriterLockSlim.IsWriteLockHeld) + { + this.lockAcquired = false; + } + else + { + readerWriterLockSlim.EnterReadLock(); + this.lockAcquired = true; + } + } + + /// + public void Dispose() + { + if (this.lockAcquired) + { + this.readerWriterLockSlim.ExitReadLock(); + } + } + } +} diff --git a/MfGames.Locking/NestableUpgradableReadLock.cs b/MfGames.Locking/NestableUpgradableReadLock.cs new file mode 100644 index 0000000..d5e4041 --- /dev/null +++ b/MfGames.Locking/NestableUpgradableReadLock.cs @@ -0,0 +1,52 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + using System; + using System.Threading; + + /// + /// Defines a ReaderWriterLockSlim upgradable read lock. + /// + public class NestableUpgradableReadLock : IDisposable + { + private readonly bool lockAcquired; + + private readonly ReaderWriterLockSlim readerWriterLockSlim; + + /// + /// Initializes a new instance of the class. + /// + /// The reader writer lock slim. + public NestableUpgradableReadLock(ReaderWriterLockSlim readerWriterLockSlim) + { + // Keep track of the lock since we'll need it to release the lock. + this.readerWriterLockSlim = readerWriterLockSlim; + + // If we already have a read or write lock, we don't do anything. + if (readerWriterLockSlim.IsUpgradeableReadLockHeld + || readerWriterLockSlim.IsWriteLockHeld) + { + this.lockAcquired = false; + } + else + { + readerWriterLockSlim.EnterUpgradeableReadLock(); + this.lockAcquired = true; + } + } + + /// + public void Dispose() + { + if (this.lockAcquired) + { + this.readerWriterLockSlim.ExitUpgradeableReadLock(); + } + } + } +} diff --git a/MfGames.Locking/NestableWriteLock.cs b/MfGames.Locking/NestableWriteLock.cs new file mode 100644 index 0000000..632dc11 --- /dev/null +++ b/MfGames.Locking/NestableWriteLock.cs @@ -0,0 +1,51 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + using System; + using System.Threading; + + /// + /// Defines a ReaderWriterLockSlim write lock. + /// + public class NestableWriteLock : IDisposable + { + private readonly bool lockAcquired; + + private readonly ReaderWriterLockSlim readerWriterLockSlim; + + /// + /// Initializes a new instance of the class. + /// + /// The reader writer lock slim. + public NestableWriteLock(ReaderWriterLockSlim readerWriterLockSlim) + { + // Keep track of the lock since we'll need it to release the lock. + this.readerWriterLockSlim = readerWriterLockSlim; + + // If we already have a read or write lock, we don't do anything. + if (readerWriterLockSlim.IsWriteLockHeld) + { + this.lockAcquired = false; + } + else + { + readerWriterLockSlim.EnterWriteLock(); + this.lockAcquired = true; + } + } + + /// + public void Dispose() + { + if (this.lockAcquired) + { + this.readerWriterLockSlim.ExitWriteLock(); + } + } + } +} diff --git a/MfGames.Locking/ReadLock.cs b/MfGames.Locking/ReadLock.cs new file mode 100644 index 0000000..9475b6e --- /dev/null +++ b/MfGames.Locking/ReadLock.cs @@ -0,0 +1,36 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + using System; + using System.Threading; + + /// + /// + /// Defines a ReaderWriterLockSlim read-only lock. + /// + public class ReadLock : IDisposable + { + private readonly ReaderWriterLockSlim readerWriterLockSlim; + + /// + /// Initializes a new instance of the class. + /// + /// The reader writer lock slim. + public ReadLock(ReaderWriterLockSlim readerWriterLockSlim) + { + this.readerWriterLockSlim = readerWriterLockSlim; + readerWriterLockSlim.EnterReadLock(); + } + + /// + public void Dispose() + { + this.readerWriterLockSlim.ExitReadLock(); + } + } +} diff --git a/MfGames.Locking/TryGetCreate.cs b/MfGames.Locking/TryGetCreate.cs new file mode 100644 index 0000000..ca0e187 --- /dev/null +++ b/MfGames.Locking/TryGetCreate.cs @@ -0,0 +1,111 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + using System; + using System.Threading; + + /// + /// Implements the basic pattern for getting an item from a cache using + /// the ReaderWriterLockSlim class. This attempts to get it using a read-only + /// lock. If that fails, it gets an upgradable lock, tries again, and if it + /// still can't find it, upgrades the lock to a write lock to create it. + /// + public static class TryGetCreate + { + /// + /// Invokes the try/get/create pattern used a condition to test for it + /// and a constructor function. + /// + /// The reader writer lock slim. + /// The condition handler. + /// The create handler. + public static void Invoke( + ReaderWriterLockSlim readerWriterLockSlim, + Func conditionHandler, + Action createHandler) + { + using (new ReadLock(readerWriterLockSlim)) + { + // Verify that the condition for creating it is false. + if (!conditionHandler()) + { + return; + } + } + + // We failed to get the lock using the read-only. We create an upgradable lock + // and try again since it may have been created with a race condition when the + // last lock was released and this one was acquired. + using (new UpgradableLock(readerWriterLockSlim)) + { + // Verify that the condition for creating it is false. + if (!conditionHandler()) + { + return; + } + + // We failed to get it in the lock. Upgrade the lock to a write and create it. + using (new WriteLock(readerWriterLockSlim)) + { + createHandler(); + } + } + } + + /// + /// Invokes the try/get/create pattern using a tryget retrieval and a + /// creator handler. + /// + /// The type of the input. + /// The type of the output. + /// The reader writer lock slim. + /// The input. + /// The try get handler. + /// The create handler. + /// The requested output object. + public static TOutput Invoke( + ReaderWriterLockSlim readerWriterLockSlim, + TInput input, + TryGetHandler tryGetHandler, + Func createHandler) + { + // First attempt to get the item using a read-only lock. + TOutput output; + + using (new ReadLock(readerWriterLockSlim)) + { + // Try to get the item using the try/get handler. + if (tryGetHandler(input, out output)) + { + // We successful got the item in the read-only cache, so just return it. + return output; + } + } + + // We failed to get the lock using the read-only. We create an upgradable lock + // and try again since it may have been created with a race condition when the + // last lock was released and this one was acquired. + using (new UpgradableLock(readerWriterLockSlim)) + { + // Try to get the item using the try/get handler. + if (tryGetHandler(input, out output)) + { + // We successful got the item in this lock, so return it without + // upgrading the lock. + return output; + } + + // We failed to get it in the lock. Upgrade the lock to a write and create it. + using (new WriteLock(readerWriterLockSlim)) + { + return createHandler(input); + } + } + } + } +} diff --git a/MfGames.Locking/TryGetHandler.cs b/MfGames.Locking/TryGetHandler.cs new file mode 100644 index 0000000..d3f26a9 --- /dev/null +++ b/MfGames.Locking/TryGetHandler.cs @@ -0,0 +1,20 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + /// + /// Defines the common try/get handler to retrieve an item of a given type. + /// + /// The type of the input or lookup key. + /// The type of the output. + /// The input value to search for. + /// The resulting output value. + /// True if the attempt was successful, otherwise false. + public delegate bool TryGetHandler( + TInput input, + out TOutput output); +} diff --git a/MfGames.Locking/UpgradableLock.cs b/MfGames.Locking/UpgradableLock.cs new file mode 100644 index 0000000..e50dc30 --- /dev/null +++ b/MfGames.Locking/UpgradableLock.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + using System; + using System.Threading; + + /// + /// Defines a ReaderWriterLockSlim read-only lock. + /// + public class UpgradableLock : IDisposable + { + private readonly ReaderWriterLockSlim readerWriterLockSlim; + + /// + /// Initializes a new instance of the class. + /// + /// The reader writer lock slim. + public UpgradableLock(ReaderWriterLockSlim readerWriterLockSlim) + { + this.readerWriterLockSlim = readerWriterLockSlim; + readerWriterLockSlim.EnterUpgradeableReadLock(); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + this.readerWriterLockSlim.ExitUpgradeableReadLock(); + } + } +} diff --git a/MfGames.Locking/WriteLock.cs b/MfGames.Locking/WriteLock.cs new file mode 100644 index 0000000..fd7d892 --- /dev/null +++ b/MfGames.Locking/WriteLock.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) Moonfire Games. +// This code is licensed under the MIT license. +// See LICENSE.md in the source or https://opensource.org/licenses/MIT +// + +namespace MfGames.Locking +{ + using System; + using System.Threading; + + /// + /// Defines a ReaderWriterLockSlim read-only lock. + /// + public class WriteLock : IDisposable + { + private readonly ReaderWriterLockSlim readerWriterLockSlim; + + /// + /// Initializes a new instance of the class. + /// + /// The reader writer lock slim. + public WriteLock(ReaderWriterLockSlim readerWriterLockSlim) + { + this.readerWriterLockSlim = readerWriterLockSlim; + readerWriterLockSlim.EnterWriteLock(); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + this.readerWriterLockSlim.ExitWriteLock(); + } + } +} diff --git a/MfGames.Locking/stylecop.json b/MfGames.Locking/stylecop.json new file mode 100644 index 0000000..68e837c --- /dev/null +++ b/MfGames.Locking/stylecop.json @@ -0,0 +1,11 @@ +{ + "$schema": + "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "Moonfire Games", + "copyrightText": + "Copyright (c) {companyName}.\nThis code is licensed under the MIT license.\nSee LICENSE.md in the source or https://opensource.org/licenses/MIT" + } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..abfdfd5 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +MfGames.Locking CIL +=================== + +This a small collection of classes that provide some simplification while working with locking in C# applications. + +``` +//using MfGames.Locking; + +ReaderWriterLockSlim locker; + +using (new ReadLock(locker)) +{ + // Do something. +} +``` \ No newline at end of file