├── .editorconfig ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── merge-dependabot.yml ├── .gitignore ├── Directory.Build.props ├── PropertyChanged.Fody.Analyzer.Tests ├── CodeGeneratorTest.CodeIsGeneratedForClassesInMultipleNamespaces.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForClassesNestedInRecord.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForClassesNestedInStruct.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForDeepNestedItems.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForNestedPartialClasses.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialClassWithAttribute.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialClassWithAttributeAndInterfaceAndBaseClass.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialClassWithAttributeInFileScopedNamespace.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialClassWithFullNameInterface.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialClassWithRedundantInterfaceImplementation.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialClassWithRedundantInterfaceImplementationAndAttributeButNotOnTheFirstPart.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialClassWithoutEventHandler.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialGenericClassWithAttribute.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedForPartialGenericClassWithoutEventHandler.verified.txt ├── CodeGeneratorTest.CodeIsGeneratedNoneVirtualForSealedPartialClassWithAttribute.verified.txt ├── CodeGeneratorTest.NoCodeIsGeneratedForPartialClass2WithAttributeAndAttributedBaseClass.verified.txt ├── CodeGeneratorTest.NoCodeIsGeneratedForPartialClass2WithAttributeAndInterfaceImplementationInBaseClass.verified.txt ├── CodeGeneratorTest.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── GlobalUsings.cs ├── PropertyChanged.Fody.Analyzer.Tests.csproj ├── SourceGeneratorTest.cs └── Usings.cs ├── PropertyChanged.Fody.Analyzer ├── AssemblyInfo.cs ├── CodeBlock.cs ├── CodeBuilder.cs ├── Configuration.cs ├── ExtensionMethods.cs ├── PropertyChanged.Fody.Analyzer.csproj ├── SourceGenerator.cs ├── SourceGeneratorEngine.cs └── TypeContext.cs ├── PropertyChanged.Fody ├── AllPropertiesFinder.cs ├── AlreadyNotifyFinder.cs ├── AttributeCleaner.cs ├── CecilExtensions.cs ├── CodeGenTypeCleaner.cs ├── CollectionCustomAttributeExtension.cs ├── Config │ ├── CheckForEqualityConfig.cs │ ├── CheckForEqualityUsingBaseEqualsConfig.cs │ ├── EnableIsChangedPropertyConfig.cs │ ├── InjectOnPropertyNameChangedConfig.cs │ ├── SuppressOnPropertyNameChangedWarningConfig.cs │ ├── SuppressWarningsConfig.cs │ ├── TriggerDependentPropertiesConfig.cs │ └── UseStaticEqualsFromBaseConfig.cs ├── DelegateHolderInjector.cs ├── DependsOnDataAttributeReader.cs ├── DoNotNotifyTypeCleaner.cs ├── EqualityCheckWeaver.cs ├── EventArgsCache.cs ├── EventArgsCacheInjector.cs ├── EventInvokerMethod.cs ├── EventInvokerNameResolver.cs ├── FilterTypeDataAttributeReader.cs ├── HasEqualityChecker.cs ├── IlGeneratedByDependencyProcessor.cs ├── IlGeneratedByDependencyReader.cs ├── InstructionListExtensions.cs ├── InterceptorFinder.cs ├── InterfaceInjector.cs ├── InvokerTypes.cs ├── IsChangedMethodFinder.cs ├── MappingFinder.cs ├── MemberMapping.cs ├── MethodFinder.cs ├── MethodGenerifier.cs ├── MethodInjector.cs ├── MethodInterceptorInjector.cs ├── ModuleWeaver.cs ├── MsCoreReferenceFinder.cs ├── NotifyInterfaceFinder.cs ├── NotifyPropertyData.cs ├── NotifyPropertyDataAttributeReader.cs ├── OnChangedMethod.cs ├── OnChangedWalker.cs ├── PropertyChanged.Fody.csproj ├── PropertyChanged.Fody.xcf ├── PropertyChangedAddMethodFinder.cs ├── PropertyData.cs ├── PropertyDataWalker.cs ├── PropertyDependency.cs ├── PropertyWeaver.cs ├── RecursiveIlFinder.cs ├── ReturnFixer.cs ├── StackOverflowChecker.cs ├── SupportsCeqChecker.cs ├── TypeEqualityFinder.cs ├── TypeNode.cs ├── TypeNodeBuilder.cs ├── TypeProcessor.cs ├── TypeResolver.cs └── WarningChecker.cs ├── PropertyChanged.sln ├── PropertyChanged.sln.DotSettings ├── PropertyChanged ├── AddINotifyPropertyChangedInterfaceAttribute.cs ├── AlsoNotifyForAttribute.cs ├── DependsOnAttribute.cs ├── DoNotCheckEqualityAttribute.cs ├── DoNotNotifyAttribute.cs ├── DoNotSetChangedAttribute.cs ├── FilterTypeAttribute.cs ├── ImplementPropertyChangedAttribute.cs ├── OnChangedMethodAttribute.cs ├── PropertyChanged.csproj ├── SuppressPropertyChangedWarningsAttribute.cs ├── Weaver.props └── key.snk ├── SmokeTest ├── Classes.cs ├── CombinedChangingAndChangedWeaverTests.NullableValueTypeProperty.Debug.verified.il ├── CombinedChangingAndChangedWeaverTests.NullableValueTypeProperty.Release.verified.il ├── CombinedChangingAndChangedWeaverTests.ReferenceTypeProperty.Debug.verified.il ├── CombinedChangingAndChangedWeaverTests.ReferenceTypeProperty.Release.verified.il ├── CombinedChangingAndChangedWeaverTests.ValueTypeProperty.Debug.verified.il ├── CombinedChangingAndChangedWeaverTests.ValueTypeProperty.Release.verified.il ├── CombinedChangingAndChangedWeaverTests.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── PartialClasses.cs └── SmokeTest.csproj ├── TestAssemblies ├── AssemblyExplicitPropertyChanged │ ├── AssemblyExplicitPropertyChanged.csproj │ └── ClassExplicitPropertyChanged.cs ├── AssemblyFSharp │ ├── AssemblyFSharp.fsproj │ ├── ClassWithNoOnPropertyChanged.fs │ └── ClassWithProperties.fs ├── AssemblyInheritingBadNamedInvoker │ ├── AssemblyInheritingBadNamedInvoker.csproj │ └── ChildClass.cs ├── AssemblyToProcess │ ├── AbstractProperty │ │ ├── ClassWithAbstractProperty.cs │ │ └── ClassWithPropertyImp.cs │ ├── AssemblyToProcess.csproj │ ├── BindableBaseTargets.cs │ ├── ClassAlreadyHasNotification.cs │ ├── ClassAlreadyHasSingleNotification.cs │ ├── ClassAlreadyHasSingleNotificationDiffParamLocation.cs │ ├── ClassAlreadyHasSingleNotificationDiffSignature.cs │ ├── ClassAlsoNotifyFor.cs │ ├── ClassAlsoNotifyForMultiple.cs │ ├── ClassCircularProperties.cs │ ├── ClassDependsOn.cs │ ├── ClassDoNotCheckEquality.cs │ ├── ClassDoNotCheckEqualityWholeClass.cs │ ├── ClassEquality.cs │ ├── ClassEqualityWithDouble.cs │ ├── ClassEqualityWithGenericClassOverload.cs │ ├── ClassEqualityWithGenericStructOverload.cs │ ├── ClassEqualityWithStruct.cs │ ├── ClassEqualityWithStructOverload.cs │ ├── ClassMissingSetGet.cs │ ├── ClassNoBackingNoEqualityField.cs │ ├── ClassNoBackingWithEqualityField.cs │ ├── ClassSetterEndsOnThrowInRelease.cs │ ├── ClassStaticProperties.cs │ ├── ClassThatIsNotSealed.cs │ ├── ClassThatIsSealed.cs │ ├── ClassWithAlsoNotifyFor.cs │ ├── ClassWithBeforeAfterAndSimpleImplementation.cs │ ├── ClassWithBeforeAfterImplementation.cs │ ├── ClassWithBeforeAfterImplementationMissingSetGet.cs │ ├── ClassWithBeforeAfterValueCheckImplementation.cs │ ├── ClassWithBoolPropUsingStringProp.cs │ ├── ClassWithBranchingReturn1.cs │ ├── ClassWithBranchingReturn2.cs │ ├── ClassWithBranchingReturnAndBeforeAfter.cs │ ├── ClassWithBranchingReturnAndNoField.cs │ ├── ClassWithCustomPropertyChanged.cs │ ├── ClassWithDependencyAfterSet.cs │ ├── ClassWithDependsOn.cs │ ├── ClassWithDependsOnAndDoNotNotify.cs │ ├── ClassWithDependsOnAndPropertyChanged.cs │ ├── ClassWithDoNotNotify.cs │ ├── ClassWithDoNotNotifyField.cs │ ├── ClassWithDoNotSetChanged.cs │ ├── ClassWithExceptionInProperty.cs │ ├── ClassWithExplicitPropertyChanged.cs │ ├── ClassWithExpression.cs │ ├── ClassWithFieldGetButNoFieldSet.cs │ ├── ClassWithGeneratedPropertyChanged.cs │ ├── ClassWithGenericAndLambda.cs │ ├── ClassWithGenericStructProp │ │ ├── ClassWithGenericStructProp.cs │ │ └── ClassWithGenericStructPropImpl.cs │ ├── ClassWithIndexer.cs │ ├── ClassWithIndexerDependsOnAndBeforeAfter.cs │ ├── ClassWithIndexerReferencingPropertyAndBeforeAfter.cs │ ├── ClassWithIndirectImplementation.cs │ ├── ClassWithInferredShouldAlsoNotifyFor.cs │ ├── ClassWithInvalidIsChangedType.cs │ ├── ClassWithInvalidOnChanged.cs │ ├── ClassWithIsChanged.cs │ ├── ClassWithLdflda.cs │ ├── ClassWithLdfldaShortCircuit.cs │ ├── ClassWithLogicInSet.cs │ ├── ClassWithNested.cs │ ├── ClassWithNotifyPropertyChangedAttribute.cs │ ├── ClassWithNotifyPropertyChangedAttributeChild.cs │ ├── ClassWithNotifyPropertyChangedAttributeChildParent.cs │ ├── ClassWithNullableBackingField.cs │ ├── ClassWithNullableGenericStruct.cs │ ├── ClassWithOnChanged.cs │ ├── ClassWithOnChangedAbstract.cs │ ├── ClassWithOnChangedAndNoPropertyChanged.cs │ ├── ClassWithOnChangedAndOnPropertyChanged.cs │ ├── ClassWithOnChangedBeforeAfter.cs │ ├── ClassWithOnChangedBeforeAfterCalculatedProperty.cs │ ├── ClassWithOnChangedBeforeAfterGeneric.cs │ ├── ClassWithOnChangedBeforeAfterTyped.cs │ ├── ClassWithOnChangedCalculatedProperty.cs │ ├── ClassWithOnChangedCustomized.cs │ ├── ClassWithOnChangedSuppressed.cs │ ├── ClassWithOpenGenerics.cs │ ├── ClassWithOwnImplementation.cs │ ├── ClassWithPropertyChangedArgImplementation.cs │ ├── ClassWithPropertySetInCatch.cs │ ├── ClassWithSenderPropertyChangedArgImplementation.cs │ ├── ClassWithSetterThatThrows.cs │ ├── ClassWithTaskReturningPropertyChangedNotifier.cs │ ├── ClassWithTernary.cs │ ├── ClassWithTryCatchInSet.cs │ ├── ClassWithWarnings.cs │ ├── CodeGenAttribute │ │ ├── ClassWithCompilerGeneratedAttribute.cs │ │ └── ClassWithGeneratedCodeAttribute.cs │ ├── ComplexHierarchy │ │ ├── ClassChild1.cs │ │ ├── ClassChild2.cs │ │ ├── ClassChild3.cs │ │ └── ClassParent.cs │ ├── FieldsFromOtherClass │ │ ├── ClassWithFieldFromOtherClass.cs │ │ └── OtherClass.cs │ ├── GenericBase │ │ ├── ClassWithGenericChild.cs │ │ ├── ClassWithGenericParent.cs │ │ ├── ClassWithIntermediateGenericBase.cs │ │ └── IntermediateGenericClass.cs │ ├── GenericBaseWithProperty │ │ ├── ClassWithGenericProperty.cs │ │ └── ClassWithGenericPropertyChild.cs │ ├── GenericBaseWithPropertyBeforeAfter │ │ ├── ClassWithGenericProperty.cs │ │ └── ClassWithGenericPropertyChild.cs │ ├── GenericBaseWithPropertyOnChanged │ │ ├── ClassWithGenericProperty.cs │ │ └── ClassWithGenericPropertyChild.cs │ ├── GenericChildWithProperty │ │ ├── ClassWithGenericProperty.cs │ │ └── ClassWithGenericPropertyChild.cs │ ├── GenericChildWithPropertyBeforeAfter │ │ ├── ClassWithGenericProperty.cs │ │ └── ClassWithGenericPropertyChild.cs │ ├── GenericChildWithPropertyOnChanged │ │ ├── ClassWithGenericProperty.cs │ │ └── ClassWithGenericPropertyChild.cs │ ├── GenericMiddle │ │ ├── ClassWithGenericMiddle.cs │ │ ├── ClassWithGenericMiddleBase.cs │ │ └── ClassWithGenericMiddleChild.cs │ ├── HierarchyBeforeAfterAndSimple │ │ ├── ClassBase.cs │ │ └── ClassChild.cs │ ├── InterfaceWithAttributes.cs │ ├── NotifyInBase │ │ ├── ClassParentWithProperty.cs │ │ └── ClassWithNotifyInBase.cs │ ├── NotifyInChild │ │ ├── ClassWithNotifyInChildByAttribute.cs │ │ ├── ClassWithNotifyInChildByInterface.cs │ │ └── ParentClass.cs │ ├── OnceRemovedINotify │ │ ├── ClassWithOnceRemovedINotify.cs │ │ └── INotifyPropertyChangedChild.cs │ ├── StructWithAttributes.cs │ ├── StructWithNotify.cs │ ├── SupportedLibraries │ │ ├── BaseClasses.cs │ │ ├── ClassCaliburn.cs │ │ ├── ClassCaliburnMicro.cs │ │ ├── ClassCaliburnOverriddenInvoker.cs │ │ ├── ClassCatel.cs │ │ ├── ClassReactiveUI.cs │ │ └── ClassTelerik.cs │ ├── TransitiveDependencies.cs │ ├── UsingPublicFieldThroughParameter │ │ ├── ClassUsingPublicFieldThroughParameter.cs │ │ └── ClassWithPublicField.cs │ ├── WithInitializedProperties │ │ ├── ClassWithAutoPropertiesInitializedInSeparateMethod.cs │ │ ├── ClassWithExplicitInitializedAutoProperties.cs │ │ ├── ClassWithExplicitInitializedAutoPropertiesDerivedProperDesign.cs │ │ ├── ClassWithExplicitInitializedAutoPropertiesDerivedWeakDesign.cs │ │ ├── ClassWithExplicitInitializedBackingFieldProperties.cs │ │ ├── ClassWithInlineInitializedAutoProperties.cs │ │ └── ObservableTestObject.cs │ └── WithOwnIsChangedImplementation │ │ ├── WithOwnIsChangedImplementation.cs │ │ └── WithOwnIsChangedImplementationInherited.cs ├── AssemblyWithAttributeAndEvent │ ├── AssemblyWithAttributeAndEvent.csproj │ └── ClassWithAttributeAndEvent.cs ├── AssemblyWithBadNamedInvoker │ ├── AssemblyWithBadNamedInvoker.csproj │ └── BaseClass.cs ├── AssemblyWithBase │ ├── AssemblyWithBase.csproj │ ├── BaseWithEquals │ │ └── BaseClass1.cs │ ├── BaseWithGenericParent │ │ ├── BaseClass1.cs │ │ └── BaseClass2.cs │ ├── DirectGeneric │ │ └── BaseClass.cs │ ├── GenericFromAbove │ │ ├── BaseClass1.cs │ │ └── BaseClass2.cs │ ├── GenericMiddle │ │ ├── BaseClassWithGenericMiddle.cs │ │ └── BaseClassWithGenericMiddleBase.cs │ ├── MultiTypes │ │ ├── BaseClass1.cs │ │ └── BaseClass2.cs │ ├── Simple │ │ ├── BaseClass.cs │ │ └── BaseClassWithVirtualProperty.cs │ ├── StaticEquals │ │ └── BaseClass.cs │ └── StaticEqualsGenericParent │ │ ├── BaseClass.cs │ │ ├── BaseClass2.cs │ │ ├── BaseClass3.cs │ │ ├── ClassUsingBase.cs │ │ ├── ClassWithOwnEquals.cs │ │ ├── ClassWithTwoBaseClasses1.cs │ │ └── ClassWithTwoBaseClasses2.cs ├── AssemblyWithBaseInDifferentModule │ ├── AssemblyWithBaseInDifferentModule.csproj │ ├── BaseWithGenericParent │ │ └── ChildClass.cs │ ├── BaseWithGenericProperty │ │ └── Class.cs │ ├── DirectGeneric │ │ └── ChildClass.cs │ ├── GenericFromAbove │ │ └── ChildClass.cs │ ├── GenericMiddle │ │ └── ClassWithGenericMiddleChildInDifferentModule.cs │ ├── Hierarchy │ │ ├── ChildClass.cs │ │ └── StaticEquals.cs │ ├── MultiTypes │ │ └── ChildClass.cs │ ├── Simple │ │ └── ChildClass.cs │ ├── StaticEquals │ │ └── StaticEquals.cs │ └── StaticEqualsGenericParent │ │ ├── ArgsMapping1.cs │ │ ├── ArgsMapping2.cs │ │ ├── OwnStaticEquals.cs │ │ ├── StaticEquals.cs │ │ └── StaticEqualsOnBase.cs ├── AssemblyWithBeforeAfterInterceptor │ ├── AssemblyWithBeforeAfterInterceptor.csproj │ ├── ClassToTest.cs │ └── PropertyNotificationInterceptor.cs ├── AssemblyWithBlockingClass │ ├── AssemblyWithBlockingClass.csproj │ └── Classes.cs ├── AssemblyWithDisabledInjectOnPropertyNameChanged │ ├── AssemblyWithDisabledInjectOnPropertyNameChanged.csproj │ ├── ClassWithConfiguredOnPropertyChanged.cs │ └── ClassWithOnPropertyChangedMethod.cs ├── AssemblyWithDisabledIsChangedProperty │ ├── AssemblyWithDisabledIsChangedProperty.csproj │ └── IsChangedClassToTest.cs ├── AssemblyWithDisabledTriggerDependentProperties │ ├── AssemblyWithDisabledTriggerDependentProperties.csproj │ └── DependentPropertiesClassToTest.cs ├── AssemblyWithExternalInheritance │ ├── AssemblyWithExternalInheritance.csproj │ └── Classes.cs ├── AssemblyWithInheritance │ ├── AssemblyWithInheritance.csproj │ └── Classes.cs ├── AssemblyWithInterceptor │ ├── AssemblyWithInterceptor.csproj │ ├── ClassToTest.cs │ └── PropertyNotificationInterceptor.cs ├── AssemblyWithNonVoidOnPropertyNameChanged │ ├── AssemblyWithNonVoidOnPropertyNameChanged.csproj │ └── ClassWithNonVoidOnPropertyChanged.cs ├── AssemblyWithStackOverflow │ ├── AssemblyWithStackOverflow.csproj │ ├── BaseClass.cs │ ├── ChildClass.cs │ ├── ChildWithBaseInDifferentAssembly.cs │ └── ClassWithStackOverflow.cs ├── AssemblyWithStaticOnPropertyNameChanged │ ├── AssemblyWithStaticOnPropertyNameChanged.csproj │ └── ClassWithNonVoidOnPropertyChanged.cs └── AssemblyWithTypeFilter │ ├── AssemblyInfo.cs │ ├── AssemblyWithTypeFilter.csproj │ ├── PropertyChangedNotificationInterceptor.cs │ ├── TestClassExclude.cs │ ├── TestClassInclude.cs │ └── TestClassIncludeAlso.cs ├── Tests ├── AlreadyNotifyFinderTest.cs ├── AssemblyExplicitPropertyChanged.cs ├── AssemblyToProcessTests.cs ├── AssemblyWithAttributeAndEventTests.cs ├── AssemblyWithBadNamedInvokerTests.cs ├── AssemblyWithBaseInDifferentModuleTests.cs ├── AssemblyWithBlockingClassTests.cs ├── AssemblyWithDisabledInjectOnPropertyNameChangedTests.cs ├── AssemblyWithDisabledIsChangedPropertyTests.cs ├── AssemblyWithDisabledTriggerDependentPropertiesTests.cs ├── AssemblyWithInheritanceTests.cs ├── AssemblyWithInterceptorTests.cs ├── AssemblyWithNonVoidOnPropertyChangedTests.Simple.verified.txt ├── AssemblyWithNonVoidOnPropertyChangedTests.cs ├── AttributeReaders │ └── DependsOnDataAttributeReaderTests.cs ├── CheckForEqualityConfigTests.cs ├── CheckForEqualityUsingBaseEqualsConfigTests.cs ├── DefinitionFinder.cs ├── EventInvokerNamesConfigTests.cs ├── EventTester.cs ├── Extensions.cs ├── FSharpTest.cs ├── GlobalUsings.cs ├── HasEqualityCheckerTests.cs ├── IlGeneratedByDependencyReaderTests │ ├── WithAutoProperties.cs │ ├── WithCamelCaseFields.cs │ ├── WithDoNotNotifyProperty.cs │ ├── WithGenericAutoProperties.cs │ ├── WithGenericFields.cs │ ├── WithLambda.cs │ ├── WithUnderScoreFields.cs │ ├── WithUpperCaseUnderScoreFields.cs │ └── WithVirtualAutoProperties.cs ├── InjectOnPropertyNameChangedTests.ModuleWeaver_WhenInjectOnPropertyNameChangedIsTrue_WarnsForNonVoidMethods.verified.txt ├── InjectOnPropertyNameChangedTests.ModuleWeaver_WhenInjectOnPropertyNameChangedIsTrue_WarnsForStaticMethods.verified.txt ├── InjectOnPropertyNameChangedTests.cs ├── MappingFinder │ ├── MappingFinderAutoPropertiesAndDodgyField.cs │ ├── MappingFinderInnerClass.cs │ ├── MappingFinderLowerCaseBackingFields.cs │ ├── MappingFinderSingleBackingConstantFieldGet.cs │ ├── MappingFinderSingleBackingFieldsGet.cs │ ├── MappingFinderSingleBackingFieldsSet.cs │ ├── MappingFinderSingleBackingReadonlyFieldGet.cs │ ├── MappingFinderUnderScoreBackingFields.cs │ └── MappingFinderWithAutoProperties.cs ├── MethodFinderTest.cs ├── MethodInjectorTests.cs ├── OnPropertyNameChangedConfigTests.cs ├── PropertyInfoCheckers │ ├── AbstractInfoCheckerTest.cs │ ├── BeforeAfterWithNoGetInfoCheckerTest.cs │ ├── CheckForEqualityWithNoBackingFieldSetInfoCheckerTest.cs │ ├── IndexerCheckerTest.cs │ └── PropertyChangedArgWithNoGetInfoCheckerTest.cs ├── RecursiveIlFinderTests.cs ├── StackOverflowCheckerTests.cs ├── SuppressOnPropertyNameChangedWarningConfigTests.cs ├── SuppressWarningsConfigTests.cs ├── Tests.csproj ├── TriggerDependentPropertiesConfigTests.cs ├── TypeEqualityFinderTests.cs └── TypeFilterTests.cs ├── appveyor.yml ├── global.json ├── license.txt ├── nuget.config ├── package_icon.png └── readme.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text 3 | 4 | # Don't check these into the repo as LF to work around TeamCity bug 5 | *.xml -text 6 | *.targets -text 7 | 8 | # Custom for Visual Studio 9 | *.cs diff=csharp 10 | *.sln merge=union 11 | *.csproj merge=union 12 | *.vbproj merge=union 13 | *.fsproj merge=union 14 | *.dbproj merge=union 15 | 16 | # Denote all files that are truly binary and should not be modified. 17 | *.dll binary 18 | *.exe binary 19 | *.png binary 20 | *.ico binary 21 | *.snk binary 22 | *.pdb binary 23 | *.svg binary 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 -------------------------------------------------------------------------------- /.github/workflows/merge-dependabot.yml: -------------------------------------------------------------------------------- 1 | name: merge-dependabot 2 | on: 3 | pull_request: 4 | jobs: 5 | automerge: 6 | runs-on: ubuntu-latest 7 | if: github.actor == 'dependabot[bot]' 8 | steps: 9 | - name: Dependabot Auto Merge 10 | uses: ahmadnassri/action-dependabot-auto-merge@v2.6.6 11 | with: 12 | target: minor 13 | github-token: ${{ secrets.GITHUB_TOKEN }} 14 | command: squash and merge -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 4.1.0 6 | preview 7 | NU5118 8 | true 9 | all 10 | low 11 | 12 | 13 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForClassesNestedInRecord.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial record Class1 12 | { 13 | partial class Class2 14 | { 15 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 16 | public event PropertyChangedEventHandler? PropertyChanged; 17 | 18 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 19 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 20 | { 21 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 22 | } 23 | 24 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 25 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 26 | { 27 | PropertyChanged?.Invoke(this, eventArgs); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForClassesNestedInStruct.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial struct Class1 12 | { 13 | partial class Class2 14 | { 15 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 16 | public event PropertyChangedEventHandler? PropertyChanged; 17 | 18 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 19 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 20 | { 21 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 22 | } 23 | 24 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 25 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 26 | { 27 | PropertyChanged?.Invoke(this, eventArgs); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialClassWithAttribute.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 : INotifyPropertyChanged 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialClassWithAttributeAndInterfaceAndBaseClass.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialClassWithAttributeInFileScopedNamespace.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | namespace Whatever 12 | { 13 | partial class Class1 : INotifyPropertyChanged 14 | { 15 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 16 | public event PropertyChangedEventHandler? PropertyChanged; 17 | 18 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 19 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 20 | { 21 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 22 | } 23 | 24 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 25 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 26 | { 27 | PropertyChanged?.Invoke(this, eventArgs); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialClassWithFullNameInterface.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialClassWithRedundantInterfaceImplementation.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialClassWithRedundantInterfaceImplementationAndAttributeButNotOnTheFirstPart.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1234 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialClassWithoutEventHandler.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialGenericClassWithAttribute.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 : INotifyPropertyChanged 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedForPartialGenericClassWithoutEventHandler.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.CodeIsGeneratedNoneVirtualForSealedPartialClassWithAttribute.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 : INotifyPropertyChanged 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | private void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | private void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.NoCodeIsGeneratedForPartialClass2WithAttributeAndAttributedBaseClass.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 : INotifyPropertyChanged 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/CodeGeneratorTest.NoCodeIsGeneratedForPartialClass2WithAttributeAndInterfaceImplementationInBaseClass.verified.txt: -------------------------------------------------------------------------------- 1 | // PropertyChanged.g.cs 2 | // 3 | #nullable enable 4 | #pragma warning disable CS0067 5 | #pragma warning disable CS8019 6 | using System.Diagnostics; 7 | using System.CodeDom.Compiler; 8 | using System.ComponentModel; 9 | using System.Runtime.CompilerServices; 10 | 11 | partial class Class1 12 | { 13 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 14 | public event PropertyChangedEventHandler? PropertyChanged; 15 | 16 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 17 | protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) 18 | { 19 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 20 | } 21 | 22 | [GeneratedCode("PropertyChanged.Fody", "TEST"), DebuggerNonUserCode] 23 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs eventArgs) 24 | { 25 | PropertyChanged?.Invoke(this, eventArgs); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 10 | 11 | 12 | 13 | 14 | A comma-separated list of error codes that can be safely ignored in assembly verification. 15 | 16 | 17 | 18 | 19 | 'false' to turn off automatic generation of the XML Schema file. 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | global using System.Text; 4 | global using AnalyzerTesting.CSharp.Extensions; 5 | global using Microsoft.CodeAnalysis; 6 | global using Microsoft.CodeAnalysis.Testing; 7 | global using Microsoft.CodeAnalysis.Testing.Verifiers; 8 | global using Microsoft.CodeAnalysis.Text; 9 | global using PropertyChanged; -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/SourceGeneratorTest.cs: -------------------------------------------------------------------------------- 1 | public class SourceGeneratorTest : 2 | CSharpIncrementalGeneratorSnapshotTest 3 | where TSourceGenerator : IIncrementalGenerator, new() 4 | { 5 | public SourceGeneratorTest(params string[] sources) 6 | { 7 | TestState.Sources.AddRange(sources.Select((source, index) => ($"File#{index}.cs", SourceText.From(source, Encoding.UTF8)))); 8 | ReferenceAssemblies = ReferenceAssemblies.NetStandard.NetStandard21; 9 | TestBehaviors = TestBehaviors.SkipGeneratedCodeCheck | TestBehaviors.SkipSuppressionCheck | TestBehaviors.SkipGeneratedSourcesCheck; 10 | 11 | this.AddReferences(typeof(AddINotifyPropertyChangedInterfaceAttribute).Assembly); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer.Tests/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("PropertyChanged.Fody.Analyzer.Tests")] 4 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer/CodeBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | class CodeBuilder 4 | { 5 | readonly StringBuilder _stringBuilder = new(); 6 | 7 | int _indent; 8 | 9 | public CodeBuilder Add(string line = "") 10 | { 11 | if (string.IsNullOrEmpty(line)) 12 | { 13 | _stringBuilder.AppendLine(); 14 | return this; 15 | } 16 | 17 | if (line.StartsWith("}")) 18 | { 19 | --_indent; 20 | } 21 | 22 | _stringBuilder.Append(' ', 4 * _indent).AppendLine(line); 23 | 24 | if (line.StartsWith("{")) 25 | { 26 | ++_indent; 27 | } 28 | 29 | return this; 30 | } 31 | 32 | public override string ToString() 33 | { 34 | return _stringBuilder.ToString(); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /PropertyChanged.Fody.Analyzer/PropertyChanged.Fody.Analyzer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0 4 | enable 5 | enable 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/AllPropertiesFinder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Mono.Cecil; 4 | 5 | public partial class ModuleWeaver 6 | { 7 | static void FindAllProperties(List notifyNodes, List list) 8 | { 9 | foreach (var node in notifyNodes) 10 | { 11 | var properties = node.TypeDefinition.Properties.ToList(); 12 | properties.AddRange(list); 13 | node.AllProperties = properties; 14 | FindAllProperties(node.Nodes, properties); 15 | } 16 | } 17 | 18 | public void FindAllProperties() 19 | { 20 | FindAllProperties(NotifyNodes, new()); 21 | } 22 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/CodeGenTypeCleaner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | static void ProcessNotifyNodes(List notifyNodes) 7 | { 8 | foreach (var node in notifyNodes.ToList()) 9 | { 10 | var customAttributes = node.TypeDefinition.CustomAttributes; 11 | if (customAttributes.ContainsAttribute("System.Runtime.CompilerServices.CompilerGeneratedAttribute")) 12 | { 13 | notifyNodes.Remove(node); 14 | continue; 15 | } 16 | ProcessNotifyNodes(node.Nodes); 17 | } 18 | } 19 | 20 | public void CleanCodeGenedTypes() 21 | { 22 | ProcessNotifyNodes(NotifyNodes); 23 | } 24 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/CheckForEqualityConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool CheckForEquality = true; 7 | 8 | public void ResolveCheckForEqualityConfig() 9 | { 10 | var value = Config?.Attributes("CheckForEquality") 11 | .Select(a => a.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | CheckForEquality = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/CheckForEqualityUsingBaseEqualsConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool CheckForEqualityUsingBaseEquals = true; 7 | 8 | public void ResolveCheckForEqualityUsingBaseEqualsConfig() 9 | { 10 | var value = Config?.Attributes("CheckForEqualityUsingBaseEquals") 11 | .Select(a => a.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | CheckForEqualityUsingBaseEquals = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/EnableIsChangedPropertyConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool EnableIsChangedProperty = true; 7 | 8 | public void ResolveEnableIsChangedPropertyConfig() 9 | { 10 | var value = Config?.Attributes("EnableIsChangedProperty") 11 | .Select(a => a.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | EnableIsChangedProperty = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/InjectOnPropertyNameChangedConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool InjectOnPropertyNameChanged = true; 7 | 8 | public void ResolveOnPropertyNameChangedConfig() 9 | { 10 | var value = Config?.Attributes("InjectOnPropertyNameChanged") 11 | .Select(a => a.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | InjectOnPropertyNameChanged = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/SuppressOnPropertyNameChangedWarningConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool SuppressOnPropertyNameChangedWarning; 7 | 8 | public void ResolveSuppressOnPropertyNameChangedWarningConfig() 9 | { 10 | var value = Config?.Attributes("SuppressOnPropertyNameChangedWarning") 11 | .Select(a => a.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | SuppressOnPropertyNameChangedWarning = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/SuppressWarningsConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool SuppressWarnings; 7 | 8 | public void ResolveSuppressWarningsConfig() 9 | { 10 | var value = Config?.Attributes("SuppressWarnings") 11 | .Select(a => a.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | SuppressWarnings = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/TriggerDependentPropertiesConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool TriggerDependentProperties = true; 7 | 8 | public void ResolveTriggerDependentPropertiesConfig() 9 | { 10 | var value = Config.Attributes("TriggerDependentProperties") 11 | .Select(_ => _.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | TriggerDependentProperties = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/Config/UseStaticEqualsFromBaseConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Xml; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | public bool UseStaticEqualsFromBase; 7 | 8 | public void ResolveUseStaticEqualsFromBaseConfig() 9 | { 10 | var value = Config?.Attributes("UseStaticEqualsFromBase") 11 | .Select(a => a.Value) 12 | .SingleOrDefault(); 13 | if (value != null) 14 | { 15 | UseStaticEqualsFromBase = XmlConvert.ToBoolean(value.ToLowerInvariant()); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/DoNotNotifyTypeCleaner.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | public partial class ModuleWeaver 5 | { 6 | static void Process(List notifyNodes) 7 | { 8 | foreach (var node in notifyNodes.ToList()) 9 | { 10 | var containsDoNotNotifyAttribute = node.TypeDefinition.CustomAttributes.ContainsAttribute("PropertyChanged.DoNotNotifyAttribute"); 11 | if (containsDoNotNotifyAttribute) 12 | { 13 | notifyNodes.Remove(node); 14 | continue; 15 | } 16 | Process(node.Nodes); 17 | } 18 | } 19 | 20 | public void CleanDoNotNotifyTypes() 21 | { 22 | Process(NotifyNodes); 23 | } 24 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/EventArgsCacheInjector.cs: -------------------------------------------------------------------------------- 1 | partial class ModuleWeaver 2 | { 3 | public void InitEventArgsCache() 4 | { 5 | EventArgsCache = new(this); 6 | } 7 | 8 | public void InjectEventArgsCache() 9 | => EventArgsCache.InjectType(); 10 | 11 | public EventArgsCache EventArgsCache; 12 | } 13 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/EventInvokerMethod.cs: -------------------------------------------------------------------------------- 1 | using Mono.Cecil; 2 | 3 | public class EventInvokerMethod 4 | { 5 | public MethodReference MethodReference; 6 | public InvokerTypes InvokerType; 7 | public bool IsVisibleFromChildren; 8 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/FilterTypeDataAttributeReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Mono.Cecil; 4 | 5 | public partial class ModuleWeaver 6 | { 7 | public List NamespaceFilters { get; private set; } 8 | 9 | public void ProcessFilterTypeAttributes() 10 | { 11 | ReadFilterTypeData(ModuleDefinition); 12 | } 13 | 14 | public void ReadFilterTypeData(ModuleDefinition moduleDefinition) 15 | { 16 | var filterTypeAttribute = moduleDefinition.Assembly.CustomAttributes.GetAttributes("PropertyChanged.FilterTypeAttribute"); 17 | if (filterTypeAttribute == null) 18 | { 19 | return; 20 | } 21 | var customAttributeArguments = filterTypeAttribute.Select(_ => _.ConstructorArguments).ToList(); 22 | NamespaceFilters = customAttributeArguments.Select(x => (string)x[0].Value).ToList(); 23 | } 24 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/IlGeneratedByDependencyProcessor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | public partial class ModuleWeaver 4 | { 5 | public void DetectIlGeneratedByDependency() 6 | { 7 | DetectIlGeneratedByDependency(NotifyNodes); 8 | } 9 | 10 | void DetectIlGeneratedByDependency(List notifyNodes) 11 | { 12 | if(!TriggerDependentProperties) 13 | { 14 | return; 15 | } 16 | 17 | foreach (var node in notifyNodes) 18 | { 19 | var ilGeneratedByDependencyReader = new IlGeneratedByDependencyReader(node); 20 | ilGeneratedByDependencyReader.Process(); 21 | DetectIlGeneratedByDependency(node.Nodes); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/InstructionListExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Mono.Cecil.Cil; 3 | using Mono.Collections.Generic; 4 | 5 | public static class InstructionListExtensions 6 | { 7 | public static void Prepend(this Collection collection, params Instruction[] instructions) 8 | { 9 | for (var index = 0; index < instructions.Length; index++) 10 | { 11 | var instruction = instructions[index]; 12 | collection.Insert(index, instruction); 13 | } 14 | } 15 | 16 | public static void Append(this Collection collection, params Instruction[] instructions) 17 | { 18 | foreach (var instruction in instructions) 19 | { 20 | collection.Add(instruction); 21 | } 22 | } 23 | 24 | public static int Insert(this Collection collection, int index, params Instruction[] instructions) 25 | { 26 | foreach (var instruction in instructions.Reverse()) 27 | { 28 | collection.Insert(index, instruction); 29 | } 30 | return index + instructions.Length; 31 | } 32 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/InvokerTypes.cs: -------------------------------------------------------------------------------- 1 | public enum InvokerTypes 2 | { 3 | String, 4 | BeforeAfter, 5 | BeforeAfterGeneric, 6 | PropertyChangedArg, 7 | SenderPropertyChangedArg 8 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/MemberMapping.cs: -------------------------------------------------------------------------------- 1 | using Mono.Cecil; 2 | 3 | public class MemberMapping 4 | { 5 | public PropertyDefinition PropertyDefinition; 6 | public FieldDefinition FieldDefinition; 7 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/NotifyPropertyData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Mono.Cecil; 3 | 4 | public class NotifyPropertyData 5 | { 6 | public List AlsoNotifyFor = new(); 7 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/OnChangedMethod.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Mono.Cecil; 3 | 4 | public enum OnChangedTypes 5 | { 6 | None, 7 | NoArg, 8 | BeforeAfter, 9 | BeforeAfterTyped 10 | } 11 | 12 | public class OnChangedMethod 13 | { 14 | public MethodReference MethodReference; 15 | public MethodDefinition MethodDefinition; 16 | public OnChangedTypes OnChangedType; 17 | public string ArgumentTypeFullName; 18 | public bool IsDefaultMethod; 19 | public List Properties = new(); 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/PropertyChanged.Fody.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/PropertyChangedAddMethodFinder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using Mono.Cecil; 5 | 6 | public static class PropertyChangedAddMethodFinder 7 | { 8 | public static IEnumerable GetPropertyChangedAddMethods(this TypeDefinition targetType) 9 | { 10 | var foundExplicit = false; 11 | 12 | foreach (var method in targetType.Methods.Where(i => i.Overrides.Any(o => o.FullName == "System.Void System.ComponentModel.INotifyPropertyChanged::add_PropertyChanged(System.ComponentModel.PropertyChangedEventHandler)"))) 13 | { 14 | foundExplicit = true; 15 | yield return method; 16 | } 17 | 18 | if (foundExplicit) 19 | { 20 | yield break; 21 | } 22 | 23 | foreach (var method in targetType.Events.Where(i => i.Name == nameof(INotifyPropertyChanged.PropertyChanged))) 24 | { 25 | yield return method.AddMethod; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/PropertyData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Mono.Cecil; 3 | 4 | public class PropertyData 5 | { 6 | public TypeNode ParentType; 7 | public FieldReference BackingFieldReference; 8 | public List AlsoNotifyFor = new(); 9 | public PropertyDefinition PropertyDefinition; 10 | public MethodReference EqualsMethod; 11 | public List AlreadyNotifies = new(); 12 | } 13 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/PropertyDependency.cs: -------------------------------------------------------------------------------- 1 | using Mono.Cecil; 2 | 3 | public class PropertyDependency 4 | { 5 | public PropertyDefinition ShouldAlsoNotifyFor; 6 | public PropertyDefinition WhenPropertyIsSet; 7 | } -------------------------------------------------------------------------------- /PropertyChanged.Fody/TypeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Mono.Cecil; 4 | 5 | public class TypeNode 6 | { 7 | public TypeDefinition TypeDefinition; 8 | public List Nodes = new(); 9 | public List PropertyDependencies = new(); 10 | public List Mappings = new(); 11 | public EventInvokerMethod EventInvoker; 12 | public MethodReference IsChangedInvoker; 13 | public List PropertyDatas = new(); 14 | public List AllProperties; 15 | public ICollection OnChangedMethods; 16 | public IEnumerable DeclaredProperties => AllProperties.Where(prop => prop.DeclaringType == TypeDefinition); 17 | } 18 | -------------------------------------------------------------------------------- /PropertyChanged.Fody/TypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Mono.Cecil; 4 | 5 | public partial class ModuleWeaver 6 | { 7 | Dictionary definitions = new(); 8 | 9 | public TypeDefinition Resolve(TypeReference reference) 10 | { 11 | if (definitions.TryGetValue(reference.FullName, out var definition)) 12 | { 13 | return definition; 14 | } 15 | return definitions[reference.FullName] = InnerResolve(reference); 16 | } 17 | 18 | static TypeDefinition InnerResolve(TypeReference reference) 19 | { 20 | TypeDefinition result; 21 | 22 | try 23 | { 24 | result = reference.Resolve(); 25 | } 26 | catch (Exception exception) 27 | { 28 | throw new($"Could not resolve '{reference.FullName}'.", exception); 29 | } 30 | 31 | if (result == null) 32 | { 33 | throw new($"Could not resolve '{reference.FullName}'. TypeReference.Resolve returned null."); 34 | } 35 | 36 | return result; 37 | } 38 | } -------------------------------------------------------------------------------- /PropertyChanged/AddINotifyPropertyChangedInterfaceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace PropertyChanged; 5 | 6 | /// 7 | /// Specifies that the class will be marked with . 8 | /// Note that all classes that implement will have property notification 9 | /// injected irrespective of the use of this attribute. 10 | /// Raising an issue about "this attribute does not behave as expected" will result in a RTFM and the issue being closed. 11 | /// 12 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)] 13 | public class AddINotifyPropertyChangedInterfaceAttribute : Attribute; -------------------------------------------------------------------------------- /PropertyChanged/AlsoNotifyForAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | // ReSharper disable UnusedParameter.Local 4 | namespace PropertyChanged; 5 | 6 | /// 7 | /// Injects this property to be notified when a dependent property is set. 8 | /// 9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] 10 | public class AlsoNotifyForAttribute : Attribute 11 | { 12 | /// 13 | /// Initializes a new instance of . 14 | /// 15 | ///A property that will be notified for. 16 | public AlsoNotifyForAttribute(string property) 17 | { 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of . 22 | /// 23 | ///A property that will be notified for. 24 | ///The properties that will be notified for. 25 | public AlsoNotifyForAttribute(string property, params string[] otherProperties) 26 | { 27 | } 28 | } 29 | // ReSharper restore UnusedParameter.Local -------------------------------------------------------------------------------- /PropertyChanged/DependsOnAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | // ReSharper disable UnusedParameter.Local 3 | 4 | namespace PropertyChanged; 5 | 6 | /// 7 | /// Injects this property to be notified when a dependent property is set. 8 | /// 9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] 10 | public class DependsOnAttribute : Attribute 11 | { 12 | /// 13 | /// Initializes a new instance of . 14 | /// 15 | /// A property that the assigned property depends on. 16 | public DependsOnAttribute(string dependency) 17 | { 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of . 22 | /// 23 | /// A property that the assigned property depends on. 24 | /// The properties that the assigned property depends on. 25 | public DependsOnAttribute(string dependency, params string[] otherDependencies) 26 | { 27 | } 28 | } 29 | // ReSharper restore UnusedParameter.Local -------------------------------------------------------------------------------- /PropertyChanged/DoNotCheckEqualityAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PropertyChanged; 4 | 5 | /// 6 | /// Skip equality check before change notification 7 | /// 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field)] 9 | public class DoNotCheckEqualityAttribute : Attribute; -------------------------------------------------------------------------------- /PropertyChanged/DoNotNotifyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PropertyChanged; 4 | 5 | /// 6 | /// Exclude a or property from notification. 7 | /// 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field, Inherited = false)] 9 | public class DoNotNotifyAttribute : Attribute; -------------------------------------------------------------------------------- /PropertyChanged/DoNotSetChangedAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PropertyChanged; 4 | 5 | /// 6 | /// Exclude a or property from IsChanged flagging. 7 | /// 8 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] 9 | public class DoNotSetChangedAttribute : Attribute; -------------------------------------------------------------------------------- /PropertyChanged/FilterTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | // ReSharper disable UnusedParameter.Local 3 | 4 | namespace PropertyChanged; 5 | 6 | /// 7 | /// Defines filters on which types to include in the 8 | /// weaving process. These filters are Regex based and 9 | /// are matched against the Type.FullName 10 | /// 11 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 12 | public class FilterTypeAttribute : Attribute 13 | { 14 | /// 15 | /// Initializes a new instance of . 16 | /// 17 | /// The filter to apply to the types in this 18 | /// assembly. Matching is done by the Regex.IsMatch method using 19 | /// the Type.FullName as input for the Matching method. 20 | /// 21 | public FilterTypeAttribute(string filter) 22 | { 23 | } 24 | } 25 | // ReSharper restore UnusedParameter.Local -------------------------------------------------------------------------------- /PropertyChanged/ImplementPropertyChangedAttribute.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 1591 2 | using System; 3 | 4 | namespace PropertyChanged; 5 | 6 | [Obsolete( 7 | message: "This configuration option has been deprecated. The use of this attribute was to add INotifyPropertyChanged to a class with its associated event definition. After that all classes that implement INotifyPropertyChanged have their properties weaved, weather they have the ImplementPropertyChangedAttribute or not. This attribute was often incorrectly interpreted as an opt in approach to having properties weaved, which was never the intent nor how it ever operated. This attribute has been replaced by AddINotifyPropertyChangedInterfaceAttribute.", 8 | error: true)] 9 | public class ImplementPropertyChangedAttribute : Attribute; -------------------------------------------------------------------------------- /PropertyChanged/OnChangedMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | // ReSharper disable UnusedParameter.Local 4 | 5 | namespace PropertyChanged; 6 | 7 | /// 8 | /// Specifies a method to call when the property value changes. 9 | /// Adding this attribute suppresses the default behavior of calling the On<PropertyName>Changed method if it exists. 10 | /// 11 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] 12 | public sealed class OnChangedMethodAttribute : Attribute 13 | { 14 | /// 15 | /// Initializes a new instance of . 16 | /// 17 | /// 18 | /// The name of a method to call when the property value changes. 19 | /// When null or empty, does not call any method - this can be used to suppress the default behavior of calling the On<PropertyName>Changed method. 20 | /// 21 | public OnChangedMethodAttribute(string methodName) 22 | { 23 | } 24 | } -------------------------------------------------------------------------------- /PropertyChanged/SuppressPropertyChangedWarningsAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PropertyChanged; 4 | 5 | /// 6 | /// Suppresses warnings emitted by PropertyChanged.Fody 7 | /// 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Method)] 9 | public sealed class SuppressPropertyChangedWarningsAttribute : Attribute; -------------------------------------------------------------------------------- /PropertyChanged/Weaver.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PropertyChanged/key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fody/PropertyChanged/a7de98072c1d4e1737cc1b304277ed14c7da09bb/PropertyChanged/key.snk -------------------------------------------------------------------------------- /SmokeTest/Classes.cs: -------------------------------------------------------------------------------- 1 | namespace SmokeTest; 2 | 3 | using System.ComponentModel; 4 | 5 | using PropertyChanged; 6 | 7 | #pragma warning disable CS0067 8 | 9 | public class Class1 : 10 | INotifyPropertyChanged 11 | { 12 | public int Property1 { get; set; } 13 | 14 | public event PropertyChangedEventHandler PropertyChanged; 15 | } 16 | 17 | [AddINotifyPropertyChangedInterface] 18 | public class Class2 19 | { 20 | public int Property1 { get; set; } 21 | } 22 | 23 | public class Class3 : 24 | INotifyPropertyChanged 25 | { 26 | [AlsoNotifyFor(nameof(Property3))] 27 | public int Property1 { get; set; } 28 | 29 | [DependsOn(nameof(Property1))] 30 | public int Property2 { get; set; } 31 | 32 | public int Property3 { get; set; } 33 | 34 | public event PropertyChangedEventHandler PropertyChanged; 35 | } 36 | 37 | public class Class4 : 38 | INotifyPropertyChanged 39 | { 40 | public bool HasChanged { get; set; } 41 | 42 | public int Property1 { get; set; } 43 | 44 | public event PropertyChangedEventHandler PropertyChanged; 45 | } -------------------------------------------------------------------------------- /SmokeTest/CombinedChangingAndChangedWeaverTests.ValueTypeProperty.Debug.verified.il: -------------------------------------------------------------------------------- 1 | .method public hidebysig specialname 2 | instance void set_Property2 ( 3 | int32 'value' 4 | ) cil managed 5 | { 6 | .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 7 | 01 00 00 00 8 | ) 9 | // Header size: 12 10 | // Code size: 45 (0x2d) 11 | .maxstack 2 12 | 13 | IL_0000: ldarg.0 14 | IL_0001: ldfld int32 SmokeTest.Testee::'k__BackingField' 15 | IL_0006: ldarg.1 16 | IL_0007: ceq 17 | IL_0009: brfalse.s IL_000d 18 | 19 | IL_000b: br.s IL_002b 20 | 21 | IL_000d: nop 22 | IL_000e: ldarg.0 23 | IL_000f: ldstr "Property2" 24 | IL_0014: callvirt instance void SmokeTest.Testee::OnPropertyChanging(string) 25 | IL_0019: ldarg.0 26 | IL_001a: ldarg.1 27 | IL_001b: stfld int32 SmokeTest.Testee::'k__BackingField' 28 | IL_0020: ldarg.0 29 | IL_0021: ldsfld class [System]System.ComponentModel.PropertyChangedEventArgs 'SmokeTest.<>PropertyChangedEventArgs'::Property2 30 | IL_0026: callvirt instance void SmokeTest.Testee::'<>OnPropertyChanged'(class [System]System.ComponentModel.PropertyChangedEventArgs) 31 | 32 | IL_002b: nop 33 | IL_002c: ret 34 | } // end of method Testee::set_Property2 35 | -------------------------------------------------------------------------------- /SmokeTest/CombinedChangingAndChangedWeaverTests.ValueTypeProperty.Release.verified.il: -------------------------------------------------------------------------------- 1 | .method public hidebysig specialname 2 | instance void set_Property2 ( 3 | int32 'value' 4 | ) cil managed 5 | { 6 | .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 7 | 01 00 00 00 8 | ) 9 | // Header size: 12 10 | // Code size: 45 (0x2d) 11 | .maxstack 2 12 | 13 | IL_0000: ldarg.0 14 | IL_0001: ldfld int32 SmokeTest.Testee::'k__BackingField' 15 | IL_0006: ldarg.1 16 | IL_0007: ceq 17 | IL_0009: brfalse.s IL_000d 18 | 19 | IL_000b: br.s IL_002b 20 | 21 | IL_000d: nop 22 | IL_000e: ldarg.0 23 | IL_000f: ldstr "Property2" 24 | IL_0014: callvirt instance void SmokeTest.Testee::OnPropertyChanging(string) 25 | IL_0019: ldarg.0 26 | IL_001a: ldarg.1 27 | IL_001b: stfld int32 SmokeTest.Testee::'k__BackingField' 28 | IL_0020: ldarg.0 29 | IL_0021: ldsfld class [System]System.ComponentModel.PropertyChangedEventArgs 'SmokeTest.<>PropertyChangedEventArgs'::Property2 30 | IL_0026: callvirt instance void SmokeTest.Testee::'<>OnPropertyChanged'(class [System]System.ComponentModel.PropertyChangedEventArgs) 31 | 32 | IL_002b: nop 33 | IL_002c: ret 34 | } // end of method Testee::set_Property2 35 | -------------------------------------------------------------------------------- /SmokeTest/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyExplicitPropertyChanged/AssemblyExplicitPropertyChanged.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | CS0067 6 | true 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyExplicitPropertyChanged/ClassExplicitPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | #pragma warning disable 649 3 | 4 | public class ClassExplicitPropertyChanged : 5 | INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged 8 | { 9 | add { } 10 | remove { } 11 | } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyFSharp/AssemblyFSharp.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | true 6 | 1.0.0 7 | 7.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyFSharp/ClassWithNoOnPropertyChanged.fs: -------------------------------------------------------------------------------- 1 | namespace Namespace 2 | 3 | open System.ComponentModel 4 | 5 | type ClassWithNoOnPropertyChanged() = 6 | let mutable propval ="" 7 | 8 | let event = new Event<_,_>() 9 | interface INotifyPropertyChanged with 10 | [] 11 | member x.PropertyChanged = event.Publish 12 | 13 | member this.Property1 14 | with get() = propval 15 | and set(v) = propval <- v -------------------------------------------------------------------------------- /TestAssemblies/AssemblyFSharp/ClassWithProperties.fs: -------------------------------------------------------------------------------- 1 | namespace Namespace 2 | 3 | open System.ComponentModel 4 | 5 | type ClassWithProperties() = 6 | let mutable propval ="" 7 | 8 | let event = new Event<_,_>() 9 | interface INotifyPropertyChanged with 10 | [] 11 | member x.PropertyChanged = event.Publish 12 | 13 | member x.OnPropertyChanged(name)= 14 | event.Trigger(x, new PropertyChangedEventArgs(name)) 15 | 16 | member this.Property1 17 | with get() = propval 18 | and set(v) = propval <- v -------------------------------------------------------------------------------- /TestAssemblies/AssemblyInheritingBadNamedInvoker/AssemblyInheritingBadNamedInvoker.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | true 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyInheritingBadNamedInvoker/ChildClass.cs: -------------------------------------------------------------------------------- 1 |  2 | public class ChildClass : BaseClass 3 | { 4 | public string Property1 { get; set; } 5 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/AbstractProperty/ClassWithAbstractProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public abstract class ClassWithAbstractProperty : 4 | INotifyPropertyChanged 5 | { 6 | public event PropertyChangedEventHandler PropertyChanged; 7 | 8 | public abstract string Property1 { get; set; } 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/AbstractProperty/ClassWithPropertyImp.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithPropertyImp : ClassWithAbstractProperty 2 | { 3 | public override string Property1 { get; set; } 4 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/AssemblyToProcess.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067;0649 6 | true 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassAlreadyHasNotification.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassAlreadyHasNotification : 4 | INotifyPropertyChanged 5 | { 6 | string property1; 7 | 8 | public string Property1 9 | { 10 | get => property1; 11 | set 12 | { 13 | property1 = value; 14 | OnPropertyChanged("Property1"); 15 | OnPropertyChanged("Property2"); 16 | } 17 | } 18 | 19 | public virtual void OnPropertyChanged(string propertyName) 20 | { 21 | PropertyChanged?.Invoke(this, new(propertyName)); 22 | } 23 | 24 | public event PropertyChangedEventHandler PropertyChanged; 25 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassAlreadyHasSingleNotification.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassAlreadyHasSingleNotification : 4 | INotifyPropertyChanged 5 | { 6 | string property1; 7 | 8 | public string Property1 9 | { 10 | get => property1; 11 | set 12 | { 13 | property1 = value; 14 | OnPropertyChanged("Property1"); 15 | } 16 | } 17 | public string Property2 => Property1; 18 | 19 | public virtual void OnPropertyChanged(string propertyName) 20 | { 21 | PropertyChanged?.Invoke(this, new(propertyName)); 22 | } 23 | 24 | public event PropertyChangedEventHandler PropertyChanged; 25 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassAlreadyHasSingleNotificationDiffParamLocation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassAlreadyHasSingleNotificationDiffParamLocation : 4 | INotifyPropertyChanged 5 | { 6 | string property1; 7 | 8 | public string Property1 9 | { 10 | get => property1; 11 | set 12 | { 13 | property1 = value; 14 | OnPropertyChanged(7, "Property1"); 15 | } 16 | } 17 | public string Property2 => Property1; 18 | 19 | public virtual void OnPropertyChanged(int fake, string propertyName) 20 | { 21 | PropertyChanged?.Invoke(this, new(propertyName)); 22 | } 23 | 24 | public event PropertyChangedEventHandler PropertyChanged; 25 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassAlreadyHasSingleNotificationDiffSignature.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassAlreadyHasSingleNotificationDiffSignature : 4 | INotifyPropertyChanged 5 | { 6 | string property1; 7 | 8 | public string Property1 9 | { 10 | get => property1; 11 | set 12 | { 13 | property1 = value; 14 | OnPropertyChanged("Property1", 5); 15 | } 16 | } 17 | 18 | public virtual void OnPropertyChanged(string propertyName, int fake) 19 | { 20 | PropertyChanged?.Invoke(this, new(propertyName)); 21 | } 22 | 23 | public event PropertyChangedEventHandler PropertyChanged; 24 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassAlsoNotifyFor.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassAlsoNotifyFor : 5 | INotifyPropertyChanged 6 | { 7 | [AlsoNotifyFor("Property2")] 8 | public string Property1 { get; set; } 9 | public string Property2 { get; set; } 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassAlsoNotifyForMultiple.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassAlsoNotifyForMultiple : 5 | INotifyPropertyChanged 6 | { 7 | [AlsoNotifyFor("Property2", "Property3")] 8 | public string Property1 { get; set; } 9 | 10 | public string Property2 { get; set; } 11 | public string Property3 { get; set; } 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassCircularProperties.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassCircularProperties : 5 | INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | [DependsOn("Self")] 10 | public string Self { get; set; } 11 | 12 | [DependsOn("PropertyA2")] 13 | public string PropertyA1 { get; set; } 14 | 15 | [DependsOn("PropertyA1")] 16 | public string PropertyA2 { get; set; } 17 | 18 | [AlsoNotifyFor("PropertyB2")] 19 | public string PropertyB1 { get; set; } 20 | 21 | [AlsoNotifyFor("PropertyB1")] 22 | public string PropertyB2 { get; set; } 23 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassDependsOn.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassDependsOn : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DependsOn("Property1")] 10 | public string Property2 { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassDoNotCheckEquality.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassDoNotCheckEquality : 4 | INotifyPropertyChanged 5 | { 6 | public int TimesProperty1Changed; 7 | public int TimesProperty2Changed; 8 | 9 | public string Property1 { get; set; } 10 | 11 | [PropertyChanged.DoNotCheckEquality] 12 | public string Property2 { get; set; } 13 | 14 | public void OnProperty1Changed() 15 | { 16 | TimesProperty1Changed += 1; 17 | } 18 | 19 | public void OnProperty2Changed() 20 | { 21 | TimesProperty2Changed += 1; 22 | } 23 | 24 | public event PropertyChangedEventHandler PropertyChanged; 25 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassDoNotCheckEqualityWholeClass.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | [PropertyChanged.DoNotCheckEquality] 4 | public class ClassDoNotCheckEqualityWholeClass : 5 | INotifyPropertyChanged 6 | { 7 | public int TimesProperty1Changed; 8 | public int TimesProperty2Changed; 9 | 10 | public string Property1 { get; set; } 11 | 12 | public string Property2 { get; set; } 13 | 14 | public void OnProperty1Changed() 15 | { 16 | TimesProperty1Changed += 1; 17 | } 18 | 19 | public void OnProperty2Changed() 20 | { 21 | TimesProperty2Changed += 1; 22 | } 23 | 24 | public event PropertyChangedEventHandler PropertyChanged; 25 | } 26 | 27 | public class ClassDoNotCheckEqualityWholeClassInherited : 28 | ClassDoNotCheckEqualityWholeClass; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassEquality.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | public class ClassEquality : 5 | INotifyPropertyChanged 6 | { 7 | DateTimeOffset? mixDateTimeOffset; 8 | public string StringProperty { get; set; } 9 | public int IntProperty { get; set; } 10 | public int? NullableIntProperty { get; set; } 11 | public bool BoolProperty { get; set; } 12 | public bool? NullableBoolProperty { get; set; } 13 | public DateTime? NullableDateTime { get; set; } 14 | public DateTime DateTime { get; set; } 15 | public DateTimeOffset? NullableDateTimeOffset { get; set; } 16 | public DateTimeOffset DateTimeOffset { get; set; } 17 | 18 | public DateTimeOffset MixDateTimeOffset 19 | { 20 | get => mixDateTimeOffset.GetValueOrDefault(); 21 | set => mixDateTimeOffset = value; 22 | } 23 | 24 | public object ObjectProperty { get; set; } 25 | public short ShortProperty { get; set; } 26 | public ushort UShortProperty { get; set; } 27 | public byte ByteProperty { get; set; } 28 | public sbyte SByteProperty { get; set; } 29 | public char CharProperty { get; set; } 30 | public event PropertyChangedEventHandler PropertyChanged; 31 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassEqualityWithDouble.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassEqualityWithDouble : 4 | INotifyPropertyChanged 5 | { 6 | public double Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassEqualityWithGenericStructOverload.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassEqualityWithGenericStructOverload : 4 | INotifyPropertyChanged 5 | { 6 | public SimpleStruct Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | #pragma warning disable 660,661 11 | public struct SimpleStruct 12 | #pragma warning restore 660,661 13 | { 14 | 15 | public int X; 16 | 17 | public static bool operator ==(SimpleStruct left, SimpleStruct right) 18 | { 19 | return left.X == right.X; 20 | } 21 | 22 | public static bool operator !=(SimpleStruct left, SimpleStruct right) 23 | { 24 | return !(left == right); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassEqualityWithStruct.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassEqualityWithStruct : 4 | INotifyPropertyChanged 5 | { 6 | public SimpleStruct Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | public struct SimpleStruct 11 | { 12 | public int X; 13 | 14 | public SimpleStruct(int x) 15 | { 16 | X = x; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassEqualityWithStructOverload.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassEqualityWithStructOverload : 4 | INotifyPropertyChanged 5 | { 6 | public SimpleStruct Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | #pragma warning disable 660,661 11 | public struct SimpleStruct 12 | #pragma warning restore 660,661 13 | { 14 | 15 | public int X; 16 | 17 | public static bool operator ==(SimpleStruct left, SimpleStruct right) 18 | { 19 | return left.X == right.X; 20 | } 21 | 22 | public static bool operator !=(SimpleStruct left, SimpleStruct right) 23 | { 24 | return !(left == right); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassMissingSetGet.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | // ReSharper disable ConvertToAutoPropertyWithPrivateSetter 3 | 4 | public class ClassMissingSetGet : 5 | INotifyPropertyChanged 6 | { 7 | string property; 8 | 9 | public string PropertyNoSet => property; 10 | 11 | 12 | public string PropertyNoGet 13 | { 14 | set => property = value; 15 | } 16 | 17 | public event PropertyChangedEventHandler PropertyChanged; 18 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassNoBackingNoEqualityField.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | // ReSharper disable ValueParameterNotUsed 3 | 4 | public class ClassNoBackingNoEqualityField : 5 | INotifyPropertyChanged 6 | { 7 | public string StringProperty 8 | { 9 | get => "Foo"; 10 | set { } 11 | } 12 | 13 | public event PropertyChangedEventHandler PropertyChanged; 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassNoBackingWithEqualityField.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | // ReSharper disable ValueParameterNotUsed 3 | 4 | public class ClassNoBackingWithEqualityField : 5 | INotifyPropertyChanged 6 | { 7 | public string StringProperty 8 | { 9 | get => "Foo"; 10 | set { } 11 | } 12 | 13 | public event PropertyChangedEventHandler PropertyChanged; 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassSetterEndsOnThrowInRelease.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | public class ClassSetterEndsOnThrowInRelease : 5 | INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | string item; 10 | 11 | public string Item 12 | { 13 | get => item; 14 | set 15 | { 16 | if (value == "Foo") 17 | { 18 | item = "Bar"; 19 | } 20 | else 21 | { 22 | throw new ArgumentOutOfRangeException(nameof(value)); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassStaticProperties.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassStaticProperties : 4 | INotifyPropertyChanged 5 | { 6 | public event PropertyChangedEventHandler PropertyChanged; 7 | public static string Property { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassThatIsNotSealed.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassThatIsNotSealed : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassThatIsSealed.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public sealed class ClassThatIsSealed : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithAlsoNotifyFor.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithAlsoNotifyFor : 5 | INotifyPropertyChanged 6 | { 7 | [AlsoNotifyFor("Property2")] 8 | public string Property1 { get; set; } 9 | public string Property2 { get; set; } 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBeforeAfterAndSimpleImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithBeforeAfterAndSimpleImplementation : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DependsOn("Property1")] 10 | public string Property2 { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | 14 | public void OnPropertyChanged(string propertyName) 15 | { 16 | } 17 | 18 | public void OnPropertyChanged(string propertyName, object before, object after) 19 | { 20 | PropertyChanged?.Invoke(this, new(propertyName)); 21 | } 22 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBeforeAfterImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithBeforeAfterImplementation : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DependsOn("Property1")] 10 | public string Property2 { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | 14 | public void OnPropertyChanged(string propertyName, object before, object after) 15 | { 16 | ValidateIsString(after); 17 | ValidateIsString(before); 18 | 19 | PropertyChanged?.Invoke(this, new(propertyName)); 20 | } 21 | 22 | static void ValidateIsString(object value) 23 | { 24 | if (value != null) 25 | { 26 | var name = value.GetType().Name; 27 | if (name != "String") 28 | { 29 | throw new($"Value should be string but is '{name}'."); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBeforeAfterImplementationMissingSetGet.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | // ReSharper disable ConvertToAutoPropertyWithPrivateSetter 3 | 4 | public class ClassWithBeforeAfterImplementationMissingSetGet : 5 | INotifyPropertyChanged 6 | { 7 | string property; 8 | 9 | public string PropertyNoSet => property; 10 | 11 | 12 | public string PropertyNoGet 13 | { 14 | set => property = value; 15 | } 16 | 17 | public event PropertyChangedEventHandler PropertyChanged; 18 | 19 | public void OnPropertyChanged(string propertyName, object before, object after) 20 | { 21 | PropertyChanged?.Invoke(this, new(propertyName)); 22 | } 23 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBeforeAfterValueCheckImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithBeforeAfterValueCheckImplementation : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DoNotNotify] 10 | public string BeforeValue1 { get; set; } 11 | 12 | [DependsOn("Property1")] 13 | public string Property2 => Property1 + "2"; 14 | 15 | [DoNotNotify] 16 | public string BeforeValue2 { get; set; } 17 | 18 | public event PropertyChangedEventHandler PropertyChanged; 19 | 20 | public void OnPropertyChanged(string propertyName, object before, object after) 21 | { 22 | if (propertyName.Equals("Property1")) 23 | { 24 | BeforeValue1 = (string)before; 25 | } 26 | 27 | if (propertyName.Equals("Property2")) 28 | { 29 | BeforeValue2 = (string)before; 30 | } 31 | 32 | PropertyChanged?.Invoke(this, new(propertyName)); 33 | } 34 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBoolPropUsingStringProp.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithBoolPropUsingStringProp: INotifyPropertyChanged 4 | { 5 | public bool StringCompareProperty => StringProperty == "magicString"; 6 | 7 | public bool BoolProperty { get; set; } 8 | 9 | string stringProperty; 10 | public string StringProperty { 11 | get => stringProperty; set 12 | { 13 | stringProperty = value; 14 | if (StringCompareProperty) 15 | { 16 | BoolProperty = true; 17 | } 18 | } 19 | } 20 | 21 | public event PropertyChangedEventHandler PropertyChanged; 22 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBranchingReturn1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | #pragma warning disable 649 4 | // ReSharper disable RedundantJumpStatement 5 | 6 | public class ClassWithBranchingReturn1 : 7 | INotifyPropertyChanged 8 | { 9 | string property1; 10 | bool isInSomeMode; 11 | 12 | public string Property1 13 | { 14 | get => property1; 15 | set 16 | { 17 | property1 = value; 18 | if (isInSomeMode) 19 | { 20 | Console.WriteLine("code here so 'if' does not get optimized away in release mode"); 21 | return; 22 | } 23 | } 24 | } 25 | 26 | public event PropertyChangedEventHandler PropertyChanged; 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBranchingReturn2.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithBranchingReturn2 : 4 | INotifyPropertyChanged 5 | { 6 | string property1; 7 | public bool HasValue; 8 | 9 | public string Property1 10 | { 11 | get => property1; 12 | set 13 | { 14 | if (HasValue) 15 | { 16 | property1 = value; 17 | } 18 | else 19 | { 20 | property1 = value; 21 | } 22 | } 23 | } 24 | 25 | public event PropertyChangedEventHandler PropertyChanged; 26 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBranchingReturnAndBeforeAfter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | #pragma warning disable 649 4 | 5 | public class ClassWithBranchingReturnAndBeforeAfter : 6 | INotifyPropertyChanged 7 | { 8 | string property1; 9 | bool isInSomeMode; 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | 12 | public string Property1 13 | { 14 | get => property1; 15 | set 16 | { 17 | property1 = value; 18 | if (isInSomeMode) 19 | { 20 | Console.WriteLine("code here so 'if' does not get optimized away in release mode"); 21 | // ReSharper disable RedundantJumpStatement 22 | return; 23 | // ReSharper restore RedundantJumpStatement 24 | } 25 | } 26 | } 27 | 28 | public void OnPropertyChanged(string propertyName, object before, object after) 29 | { 30 | PropertyChanged?.Invoke(this, new(propertyName)); 31 | } 32 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithBranchingReturnAndNoField.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | // ReSharper disable ValueParameterNotUsed 3 | // ReSharper disable NotAccessedField.Local 4 | 5 | public class ClassWithBranchingReturnAndNoField : 6 | INotifyPropertyChanged 7 | { 8 | int x; 9 | public bool HasValue; 10 | 11 | public string Property1 12 | { 13 | get => null; 14 | set 15 | { 16 | if (HasValue) 17 | { 18 | x++; 19 | } 20 | else 21 | { 22 | x++; 23 | } 24 | } 25 | } 26 | 27 | public event PropertyChangedEventHandler PropertyChanged; 28 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithCustomPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithCustomPropertyChanged : 4 | INotifyPropertyChanged 5 | { 6 | // ReSharper disable NotAccessedField.Local 7 | PropertyChangedEventHandler propertyChanged; 8 | // ReSharper restore NotAccessedField.Local 9 | 10 | public event PropertyChangedEventHandler PropertyChanged 11 | { 12 | add => propertyChanged += value; 13 | remove => propertyChanged -= value; 14 | } 15 | 16 | public string Property1 { get; set; } 17 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithDependencyAfterSet.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithDependencyAfterSet : 4 | INotifyPropertyChanged 5 | { 6 | public event PropertyChangedEventHandler PropertyChanged; 7 | 8 | string property2; 9 | 10 | // ReSharper disable ConvertToAutoProperty 11 | public string Property2 12 | { 13 | get => property2; 14 | set => property2 = value; 15 | } 16 | // ReSharper restore ConvertToAutoProperty 17 | 18 | string property1; 19 | 20 | public string Property1 21 | { 22 | get => property1; 23 | set 24 | { 25 | property1 = value; 26 | Property2 = value; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithDependsOn.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithDependsOn : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | [DependsOn("Property1")] 9 | public string Property2 { get; set; } 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithDependsOnAndDoNotNotify.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithDependsOnAndDoNotNotify : 5 | INotifyPropertyChanged 6 | { 7 | [DoNotNotify] 8 | public string UseLessProperty { get; set; } 9 | 10 | public string Property1 { get; set; } 11 | public string Property2 => Property1; 12 | 13 | public event PropertyChangedEventHandler PropertyChanged; 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithDependsOnAndPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithDependsOnAndPropertyChanged : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | [DependsOn("Property1")] 9 | public string Property2 { get; set; } 10 | 11 | public int Property2ChangedCalled = 0; 12 | 13 | private void OnProperty2Changed() => Property2ChangedCalled++; 14 | 15 | 16 | public event PropertyChangedEventHandler PropertyChanged; 17 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithDoNotNotify.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | [DoNotNotify] 5 | public class ClassWithDoNotNotify : 6 | INotifyPropertyChanged 7 | { 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithDoNotNotifyField.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithDoNotNotifyField : 5 | INotifyPropertyChanged 6 | { 7 | [field: DoNotNotify] 8 | public string Property1 { get; set; } 9 | 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithDoNotSetChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithDoNotSetChanged : 5 | INotifyPropertyChanged 6 | { 7 | [DoNotSetChanged] 8 | public string Property1 { get; set; } 9 | 10 | public bool IsChanged { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithExceptionInProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | public class ClassWithExceptionInProperty : 5 | INotifyPropertyChanged 6 | { 7 | public string Property 8 | { 9 | get => throw new NotImplementedException(); 10 | set => throw new NotImplementedException(); 11 | } 12 | 13 | public event PropertyChangedEventHandler PropertyChanged; 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithExplicitPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithExplicitPropertyChanged : 4 | INotifyPropertyChanged 5 | { 6 | // ReSharper disable NotAccessedField.Local 7 | PropertyChangedEventHandler propertyChanged; 8 | // ReSharper restore NotAccessedField.Local 9 | 10 | event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged 11 | { 12 | add => propertyChanged += value; 13 | remove => propertyChanged -= value; 14 | } 15 | 16 | public string Property1 { get; set; } 17 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq.Expressions; 4 | // ReSharper disable UnusedVariable 5 | 6 | public class ClassWithExpression : 7 | INotifyPropertyChanged 8 | { 9 | public string Property1; 10 | 11 | public ClassWithExpression() 12 | { 13 | Expression> expressionFunc = _ => _.Property1; 14 | Func func = _ => _.Property1; 15 | 16 | Action expression2 = (expression, s) => { expression.Property1 = s; }; 17 | } 18 | 19 | public event PropertyChangedEventHandler PropertyChanged; 20 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithFieldGetButNoFieldSet.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithFieldGetButNoFieldSet : 4 | INotifyPropertyChanged 5 | { 6 | string property; 7 | 8 | public string Property1 9 | { 10 | get => property; 11 | set => SetField(value); 12 | } 13 | 14 | void SetField(string value) 15 | { 16 | property = value; 17 | } 18 | 19 | public event PropertyChangedEventHandler PropertyChanged; 20 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithGeneratedPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom.Compiler; 2 | using System.ComponentModel; 3 | using PropertyChanged; 4 | 5 | public class ClassWithGeneratedPropertyChangedBase; 6 | 7 | [AddINotifyPropertyChangedInterface] 8 | public class ClassWithGeneratedPropertyChanged : ClassWithGeneratedPropertyChangedBase, INotifyPropertyChanged 9 | { 10 | public string Property1 { get; set; } 11 | 12 | [GeneratedCode("PropertyChanged.Fody", "TEST")] 13 | public event PropertyChangedEventHandler PropertyChanged; 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithGenericAndLambda.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | 5 | public class ClassWithGenericAndLambda : 6 | INotifyPropertyChanged 7 | { 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | public string Property1 { get; set; } 11 | 12 | public void MethodWithLambda(object data) 13 | { 14 | var list = new List(); 15 | list.First(container => container == data); 16 | } 17 | } 18 | 19 | public class ClassWithGenericAndLambdaImp : 20 | ClassWithGenericAndLambda; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithGenericStructProp/ClassWithGenericStructProp.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithGenericStructProp : INotifyPropertyChanged where T : struct 4 | { 5 | public T? Property1 { get; set; } 6 | 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithGenericStructProp/ClassWithGenericStructPropImpl.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithGenericStructPropImpl : ClassWithGenericStructProp; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithIndexer.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithIndexer : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | string[] arr = new string[100]; 8 | 9 | public string this[int i] 10 | { 11 | get => arr[i]; 12 | set => arr[i] = value; 13 | } 14 | 15 | public event PropertyChangedEventHandler PropertyChanged; 16 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithIndexerDependsOnAndBeforeAfter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithIndexerDependsOnAndBeforeAfter : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DependsOn(nameof(Property1))] 10 | public string this[int i] 11 | { 12 | get => null; 13 | } 14 | 15 | public void OnPropertyChanged(string propertyName, object before, object after) 16 | { 17 | PropertyChanged?.Invoke(this, new(propertyName)); 18 | } 19 | 20 | public event PropertyChangedEventHandler PropertyChanged; 21 | } 22 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithIndexerReferencingPropertyAndBeforeAfter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithIndexerReferencingPropertyAndBeforeAfter : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public string this[int i] 9 | { 10 | get => Property1; 11 | } 12 | 13 | public void OnPropertyChanged(string propertyName, object before, object after) 14 | { 15 | PropertyChanged?.Invoke(this, new(propertyName)); 16 | } 17 | 18 | public event PropertyChangedEventHandler PropertyChanged; 19 | } 20 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithIndirectImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithIndirectImplementation : 4 | Indirect 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } 10 | 11 | public interface Indirect : 12 | INotifyPropertyChanged; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithInferredShouldAlsoNotifyFor.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithInferredShouldAlsoNotifyFor : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | public string Property2 => Property1; 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithInvalidIsChangedType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithInvalidIsChangedType : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | public string IsChanged { get; set; } 8 | 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithIsChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithIsChanged : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | public bool IsChanged { get; set; } 8 | 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithLdflda.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithLdflda : 4 | INotifyPropertyChanged 5 | { 6 | decimal? property1; 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | public decimal? Property1 10 | { 11 | get => property1; 12 | set 13 | { 14 | if (value == 0.0m) 15 | { 16 | property1 = null; 17 | } 18 | else 19 | { 20 | property1 = value; 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithLdfldaShortCircuit.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithLdfldaShortCircuit : 4 | INotifyPropertyChanged 5 | { 6 | decimal? property1; 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | public decimal? Property1 10 | { 11 | get => property1; 12 | set 13 | { 14 | if (value == 0.0m) 15 | { 16 | if (property1 == null) 17 | { 18 | return; 19 | } 20 | property1 = null; 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithLogicInSet.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Diagnostics; 3 | 4 | public class ClassWithLogicInSet : 5 | INotifyPropertyChanged 6 | { 7 | 8 | string property1; 9 | 10 | public string Property1 11 | { 12 | get => property1; 13 | set 14 | { 15 | Debug.WriteLine("Foo"); 16 | property1 = value; 17 | Debug.WriteLine("Bar"); 18 | } 19 | } 20 | 21 | public event PropertyChangedEventHandler PropertyChanged; 22 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithNested.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithNested 4 | { 5 | public class ClassNested : 6 | INotifyPropertyChanged { 7 | public string Property1 { get; set; } 8 | 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | 11 | public class ClassNestedNested : 12 | INotifyPropertyChanged { 13 | public string Property1 { get; set; } 14 | 15 | public event PropertyChangedEventHandler PropertyChanged; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithNotifyPropertyChangedAttribute.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | [AddINotifyPropertyChangedInterface] 4 | public class ClassWithNotifyPropertyChangedAttribute 5 | { 6 | public string Property1 { get; set; } 7 | } 8 | 9 | [AddINotifyPropertyChangedInterface] 10 | public class ClassWithNotifyPropertyChangedAttributeGeneric 11 | { 12 | public string Property1 { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithNotifyPropertyChangedAttributeChild.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | [AddINotifyPropertyChangedInterface] 4 | public class ClassWithNotifyPropertyChangedAttributeChild : ClassWithNotifyPropertyChangedAttributeChildParent 5 | { 6 | public string Property1 { get; set; } 7 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithNotifyPropertyChangedAttributeChildParent.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | [AddINotifyPropertyChangedInterface] 4 | public class ClassWithNotifyPropertyChangedAttributeChildParent 5 | { 6 | public string Property2 { get; set; } 7 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithNullableBackingField.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithNullableBackingField : INotifyPropertyChanged 4 | { 5 | bool? _isFlag; 6 | 7 | public bool IsFlag 8 | { 9 | get => _isFlag ?? (_isFlag = GetFlag()).Value; 10 | set => _isFlag = value; 11 | } 12 | 13 | // ReSharper disable once MemberCanBeMadeStatic.Local 14 | bool GetFlag() => false; 15 | 16 | public event PropertyChangedEventHandler PropertyChanged; 17 | } 18 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithNullableGenericStruct.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | [AddINotifyPropertyChangedInterface] 4 | public class ParentOfNullableGenericStruct 5 | { 6 | public GenericStruct? ChildProperty { get; set; } 7 | } 8 | 9 | public struct GenericStruct 10 | { 11 | public T Value { get; } 12 | } 13 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOnChanged : 4 | INotifyPropertyChanged 5 | { 6 | public bool OnProperty1ChangedCalled; 7 | 8 | public string Property1 { get; set; } 9 | 10 | public void OnProperty1Changed() 11 | { 12 | OnProperty1ChangedCalled = true; 13 | } 14 | 15 | public event PropertyChangedEventHandler PropertyChanged; 16 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedAbstract.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public abstract class ClassWithOnChangedAbstract : 4 | INotifyPropertyChanged 5 | { 6 | public bool OnProperty1ChangedCalled; 7 | 8 | public string Property1 { get; set; } 9 | public abstract void OnProperty1Changed(); 10 | 11 | public event PropertyChangedEventHandler PropertyChanged; 12 | } 13 | 14 | public class ClassWithOnChangedConcrete : 15 | ClassWithOnChangedAbstract 16 | { 17 | public override void OnProperty1Changed() 18 | { 19 | OnProperty1ChangedCalled = true; 20 | } 21 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedAndNoPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOnChangedAndNoPropertyChanged : 4 | INotifyPropertyChanged 5 | { 6 | public int OnProperty1ChangedCalled; 7 | string property1; 8 | 9 | public string Property1 10 | { 11 | get => property1; 12 | set 13 | { 14 | property1 = value; 15 | OnProperty1Changed(); 16 | } 17 | } 18 | 19 | public void OnProperty1Changed() 20 | { 21 | OnProperty1ChangedCalled++; 22 | } 23 | 24 | public event PropertyChangedEventHandler PropertyChanged; 25 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedAndOnPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOnChangedAndOnPropertyChanged : 4 | INotifyPropertyChanged 5 | { 6 | public int OnProperty1ChangedCalled; 7 | string property1; 8 | 9 | public string Property1 10 | { 11 | get => property1; 12 | set 13 | { 14 | property1 = value; 15 | OnPropertyChanged("Property1"); 16 | OnProperty1Changed(); 17 | } 18 | } 19 | 20 | public void OnProperty1Changed() 21 | { 22 | OnProperty1ChangedCalled++; 23 | } 24 | 25 | public event PropertyChangedEventHandler PropertyChanged; 26 | 27 | public virtual void OnPropertyChanged(string propertyName) 28 | { 29 | PropertyChanged?.Invoke(this, new(propertyName)); 30 | } 31 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedBeforeAfter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOnChangedBeforeAfter : 4 | INotifyPropertyChanged 5 | { 6 | public bool OnProperty1ChangedCalled; 7 | public bool OnProperty2ChangedCalled; 8 | 9 | public string Property1 { get; set; } 10 | public string Property2 { get; set; } 11 | 12 | public void OnProperty1Changed() 13 | { 14 | OnProperty1ChangedCalled = true; 15 | } 16 | 17 | public void OnProperty2Changed(object before, object after) 18 | { 19 | OnProperty2ChangedCalled = true; 20 | } 21 | 22 | public void OnPropertyChanged(string propertyName, object before, object after) 23 | { 24 | PropertyChanged?.Invoke(this, new(propertyName)); 25 | } 26 | 27 | public event PropertyChangedEventHandler PropertyChanged; 28 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedBeforeAfterCalculatedProperty.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | [AddINotifyPropertyChangedInterface] 4 | public class ClassWithOnChangedBeforeAfterCalculatedProperty 5 | { 6 | 7 | public string Property1 { get; set; } 8 | public int Property2 => Property1?.Length ?? 0; 9 | 10 | public string Property2ChangeValue; 11 | 12 | public void OnProperty2Changed(object before, object after) 13 | { 14 | Property2ChangeValue = $"From {before} to {after}"; 15 | } 16 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedBeforeAfterGeneric.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOnChangedBeforeAfterGeneric : 4 | INotifyPropertyChanged 5 | { 6 | public bool GenericOnPropertyChangedCalled; 7 | 8 | public string Property1 { get; set; } 9 | 10 | public void OnPropertyChanged(string propertyName, T before, T after) 11 | { 12 | GenericOnPropertyChangedCalled = true; 13 | PropertyChanged(this, new(propertyName)); 14 | } 15 | 16 | public event PropertyChangedEventHandler PropertyChanged; 17 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedCalculatedProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOnChangedCalculatedProperty : 4 | INotifyPropertyChanged 5 | { 6 | public bool OnProperty2ChangedCalled; 7 | public bool OnProperty3ChangedCalled; 8 | 9 | public string Property1 { get; set; } 10 | public string Property2 => $"{Property1}!"; 11 | public string Property3 => $"{Property2}!"; 12 | 13 | public void OnProperty2Changed() 14 | { 15 | OnProperty2ChangedCalled = true; 16 | } 17 | 18 | public void OnProperty3Changed() 19 | { 20 | OnProperty3ChangedCalled = true; 21 | } 22 | 23 | public event PropertyChangedEventHandler PropertyChanged; 24 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOnChangedSuppressed.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithOnChangedSuppressed : 5 | INotifyPropertyChanged 6 | { 7 | public bool OnProperty1ChangedCalled; 8 | public bool OnProperty2ChangedCalled; 9 | 10 | [OnChangedMethod(null)] 11 | public string Property1 { get; set; } 12 | 13 | [OnChangedMethod("")] 14 | public string Property2 { get; set; } 15 | 16 | public void OnProperty1Changed() 17 | { 18 | OnProperty1ChangedCalled = true; 19 | } 20 | 21 | public void OnProperty2Changed() 22 | { 23 | OnProperty2ChangedCalled = true; 24 | } 25 | 26 | public event PropertyChangedEventHandler PropertyChanged; 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOpenGenerics.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using PropertyChanged; 5 | 6 | [AddINotifyPropertyChangedInterface] 7 | public class ClassWithOpenGenerics 8 | { 9 | public KeyValuePair Property1 { get; set; } 10 | 11 | public Tuple Property2 { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithOwnImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOwnImplementation : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | public bool BaseNotifyCalled { get; set; } 8 | 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | 11 | public virtual void OnPropertyChanged(string propertyName) 12 | { 13 | BaseNotifyCalled = true; 14 | PropertyChanged?.Invoke(this, new(propertyName)); 15 | } 16 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithPropertyChangedArgImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithPropertyChangedArgImplementation : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DependsOn("Property1")] 10 | public string Property2 { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | 14 | public void OnPropertyChanged(PropertyChangedEventArgs arg) 15 | { 16 | PropertyChanged?.Invoke(this, arg); 17 | } 18 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithPropertySetInCatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | public class ClassWithPropertySetInCatch:INotifyPropertyChanged 5 | { 6 | string property1; 7 | public string Property1 { 8 | get => property1; set 9 | { 10 | try 11 | { 12 | throw new ArgumentException(); 13 | } 14 | catch (ArgumentException) 15 | { 16 | property1 = value; 17 | } 18 | } 19 | } 20 | 21 | public event PropertyChangedEventHandler PropertyChanged; 22 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithSenderPropertyChangedArgImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public class ClassWithSenderPropertyChangedArgImplementation : 5 | INotifyPropertyChanged 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DependsOn("Property1")] 10 | public string Property2 { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | 14 | public void OnPropertyChanged(object sender, PropertyChangedEventArgs arg) 15 | { 16 | PropertyChanged?.Invoke(sender, arg); 17 | } 18 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithSetterThatThrows.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | public class ClassWithSetterThatThrows : 5 | INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | public string Item 10 | { 11 | get => "Foo"; 12 | set => throw new NotSupportedException("Obsolete Setter"); 13 | } 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithTaskReturningPropertyChangedNotifier.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using System.Threading.Tasks; 4 | 5 | public class ClassWithTaskReturningPropertyChangedNotifier : 6 | INotifyPropertyChanged 7 | { 8 | public string Property1 { get; set; } 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | 11 | public virtual Task RaisePropertyChanged([CallerMemberName] string whichProperty = "") 12 | { 13 | var changedArgs = new PropertyChangedEventArgs(whichProperty); 14 | return RaisePropertyChanged(changedArgs); 15 | } 16 | 17 | async Task RaisePropertyChanged(PropertyChangedEventArgs changedArgs) 18 | { 19 | void raiseChange() 20 | { 21 | PropertyChanged?.Invoke(this, changedArgs); 22 | } 23 | 24 | await Task.Run(() => raiseChange()); 25 | } 26 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithTernary.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithTernary : 4 | INotifyPropertyChanged 5 | { 6 | decimal? property1; 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | public decimal? Property1 10 | { 11 | get => property1; 12 | set 13 | { 14 | var newValue = value == 0.0m ? null : value; 15 | if (property1 != newValue) 16 | { 17 | property1 = newValue; 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithTryCatchInSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | public class ClassWithTryCatchInSet:INotifyPropertyChanged 5 | { 6 | string property1; 7 | public string Property1 { 8 | get => property1; set 9 | { 10 | try 11 | { 12 | property1 = value; 13 | } 14 | catch (ArgumentException) 15 | { 16 | // actually, 'call OnPropertyChanged' inserted here, it's wrong. 17 | } 18 | } 19 | } 20 | 21 | public event PropertyChangedEventHandler PropertyChanged; 22 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ClassWithWarnings.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using PropertyChanged; 3 | 4 | 5 | [AddINotifyPropertyChangedInterface] 6 | public class ClassWithWarningsBase 7 | { 8 | public string BaseClassProperty { get; set; } 9 | } 10 | 11 | [AddINotifyPropertyChangedInterface] 12 | public class ClassWithWarnings : ClassWithWarningsBase 13 | { 14 | 15 | [DoNotNotify] 16 | public string Property1 { get; set; } 17 | 18 | [OnChangedMethod(nameof(CallThisInstead))] 19 | public string Property2 { get; set; } 20 | 21 | public bool Property1ChangedCalled; 22 | public bool Property2ChangedCalled; 23 | public bool PropertyXChangedCalled; 24 | public bool CallThisInsteadCalled; 25 | 26 | 27 | void OnProperty1Changed() => Trace.WriteLine("Ignored"); 28 | 29 | void OnProperty2Changed() => Trace.WriteLine("Ignored"); 30 | 31 | void OnPropertyXChanged() => Trace.WriteLine("Ignored"); 32 | void OnBaseClassPropertyChanged() => Trace.WriteLine("Ignored"); 33 | 34 | void CallThisInstead() => Trace.WriteLine("Ignored"); 35 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/CodeGenAttribute/ClassWithCompilerGeneratedAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | 4 | [CompilerGenerated] 5 | public class ClassWithCompilerGeneratedAttribute : 6 | INotifyPropertyChanged 7 | { 8 | public string Property1 { get; set; } 9 | 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/CodeGenAttribute/ClassWithGeneratedCodeAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom.Compiler; 2 | using System.ComponentModel; 3 | 4 | [GeneratedCode("asd", "asd")] 5 | public class ClassWithGeneratedCodeAttribute : 6 | INotifyPropertyChanged 7 | { 8 | public string Property1 { get; set; } 9 | 10 | public event PropertyChangedEventHandler PropertyChanged; 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ComplexHierarchy/ClassChild1.cs: -------------------------------------------------------------------------------- 1 | namespace ComplexHierarchy; 2 | 3 | public class ClassChild1 : ClassParent 4 | { 5 | public string Property1 { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ComplexHierarchy/ClassChild2.cs: -------------------------------------------------------------------------------- 1 | namespace ComplexHierarchy; 2 | 3 | public class ClassChild2 : ClassParent 4 | { 5 | public string Property1 { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ComplexHierarchy/ClassChild3.cs: -------------------------------------------------------------------------------- 1 | namespace ComplexHierarchy; 2 | 3 | public class ClassChild3 : ClassChild2 4 | { 5 | public string Property2 { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/ComplexHierarchy/ClassParent.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace ComplexHierarchy; 4 | 5 | public class ClassParent: INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/FieldsFromOtherClass/ClassWithFieldFromOtherClass.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithFieldFromOtherClass : 4 | INotifyPropertyChanged 5 | { 6 | OtherClass otherClass = new(); 7 | 8 | public string Property1 9 | { 10 | get => otherClass.property1; 11 | set => otherClass.property1 = value; 12 | } 13 | 14 | public event PropertyChangedEventHandler PropertyChanged; 15 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/FieldsFromOtherClass/OtherClass.cs: -------------------------------------------------------------------------------- 1 | public class OtherClass 2 | { 3 | public string property1; 4 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBase/ClassWithGenericChild.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithGenericChild : ClassWithGenericParent; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBase/ClassWithGenericParent.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithGenericParent : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBase/ClassWithIntermediateGenericBase.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithIntermediateGenericBase : IntermediateGenericClass 2 | { 3 | public string Property3 { get; set; } 4 | } 5 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBase/IntermediateGenericClass.cs: -------------------------------------------------------------------------------- 1 | public class IntermediateGenericClass : ClassWithGenericParent 2 | { 3 | public string Property2 { get; set; } 4 | } 5 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBaseWithProperty/ClassWithGenericProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace GenericBaseWithProperty; 4 | 5 | public class ClassWithGenericPropertyParent : 6 | INotifyPropertyChanged { 7 | public T Property1 { get; set; } 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBaseWithProperty/ClassWithGenericPropertyChild.cs: -------------------------------------------------------------------------------- 1 | namespace GenericBaseWithProperty; 2 | 3 | public class ClassWithGenericPropertyChild : ClassWithGenericPropertyParent; 4 | 5 | public class ClassWithGenericPropertyDouble : ClassWithGenericPropertyParent; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBaseWithPropertyBeforeAfter/ClassWithGenericProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace GenericBaseWithPropertyBeforeAfter; 4 | 5 | public class ClassWithGenericPropertyParent : 6 | INotifyPropertyChanged { 7 | public T Property1 { get; set; } 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | public void OnPropertyChanged(string propertyName, object before, object after) 10 | { 11 | PropertyChanged?.Invoke(this, new(propertyName)); 12 | } 13 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBaseWithPropertyBeforeAfter/ClassWithGenericPropertyChild.cs: -------------------------------------------------------------------------------- 1 | namespace GenericBaseWithPropertyBeforeAfter; 2 | 3 | public class ClassWithGenericPropertyChild : ClassWithGenericPropertyParent; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBaseWithPropertyOnChanged/ClassWithGenericProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace GenericBaseWithPropertyOnChanged; 4 | 5 | public class ClassWithGenericPropertyParent : 6 | INotifyPropertyChanged { 7 | public bool OnProperty1ChangedCalled; 8 | public bool OnProperty2ChangedCalled; 9 | 10 | public T Property1 { get; set; } 11 | public void OnProperty1Changed() 12 | { 13 | OnProperty1ChangedCalled = true; 14 | } 15 | 16 | public T Property2 { get; set; } 17 | public void OnProperty2Changed() 18 | { 19 | OnProperty2ChangedCalled = true; 20 | } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericBaseWithPropertyOnChanged/ClassWithGenericPropertyChild.cs: -------------------------------------------------------------------------------- 1 | namespace GenericBaseWithPropertyOnChanged; 2 | 3 | public class ClassWithGenericPropertyChild : ClassWithGenericPropertyParent; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericChildWithProperty/ClassWithGenericProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace GenericChildWithProperty; 4 | 5 | public class ClassWithGenericPropertyParent : 6 | INotifyPropertyChanged 7 | { 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericChildWithProperty/ClassWithGenericPropertyChild.cs: -------------------------------------------------------------------------------- 1 | namespace GenericChildWithProperty; 2 | 3 | public class ClassWithGenericPropertyChild : ClassWithGenericPropertyParent 4 | { 5 | public string Property1 { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericChildWithPropertyBeforeAfter/ClassWithGenericProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace GenericChildWithPropertyBeforeAfter; 4 | 5 | public class ClassWithGenericPropertyParent : 6 | INotifyPropertyChanged { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | public void OnPropertyChanged(string propertyName, object before, object after) 9 | { 10 | PropertyChanged?.Invoke(this, new(propertyName)); 11 | } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericChildWithPropertyBeforeAfter/ClassWithGenericPropertyChild.cs: -------------------------------------------------------------------------------- 1 | namespace GenericChildWithPropertyBeforeAfter; 2 | 3 | public class ClassWithGenericPropertyChild : ClassWithGenericPropertyParent 4 | { 5 | public string Property1 { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericChildWithPropertyOnChanged/ClassWithGenericProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace GenericChildWithPropertyOnChanged; 4 | 5 | public class ClassWithGenericPropertyParent : 6 | INotifyPropertyChanged { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericChildWithPropertyOnChanged/ClassWithGenericPropertyChild.cs: -------------------------------------------------------------------------------- 1 | namespace GenericChildWithPropertyOnChanged; 2 | 3 | public class ClassWithGenericPropertyChild : ClassWithGenericPropertyParent 4 | { 5 | public bool OnProperty1ChangedCalled; 6 | 7 | public string Property1 { get; set; } 8 | public void OnProperty1Changed() 9 | { 10 | OnProperty1ChangedCalled = true; 11 | } 12 | 13 | public bool OnProperty2ChangedCalled; 14 | 15 | public string Property2 { get; set; } 16 | public void OnProperty2Changed() 17 | { 18 | OnProperty2ChangedCalled = true; 19 | } 20 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericMiddle/ClassWithGenericMiddle.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithGenericMiddle : ClassWithGenericMiddleBase 2 | { 3 | public string Property2 { get; set; } 4 | } 5 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericMiddle/ClassWithGenericMiddleBase.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithGenericMiddleBase : INotifyPropertyChanged 4 | { 5 | public string Property1 { get; set; } 6 | 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } 9 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/GenericMiddle/ClassWithGenericMiddleChild.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithGenericMiddleChild : ClassWithGenericMiddle 2 | { 3 | public int Property3 { get; set; } 4 | } 5 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/HierarchyBeforeAfterAndSimple/ClassBase.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace HierarchyBeforeAfterAndSimple; 4 | 5 | public class ClassBase : 6 | INotifyPropertyChanged 7 | { 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | public void OnPropertyChanged(string propertyName) 11 | { 12 | PropertyChanged?.Invoke(this, new(propertyName)); 13 | } 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/HierarchyBeforeAfterAndSimple/ClassChild.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | namespace HierarchyBeforeAfterAndSimple; 4 | 5 | public class ClassChild : ClassBase 6 | { 7 | public string Property1 { get; set; } 8 | 9 | [DoNotNotify] 10 | public bool BeforeAfterCalled { get; set; } 11 | 12 | public void OnPropertyChanged(string propertyName, object before, object after) 13 | { 14 | BeforeAfterCalled = true; 15 | OnPropertyChanged(propertyName); 16 | } 17 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/InterfaceWithAttributes.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | public interface InterfaceWithAttributes 4 | { 5 | [DependsOn("a")] 6 | [DoNotNotify] 7 | string Property1 { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/NotifyInBase/ClassParentWithProperty.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassParentWithProperty : 4 | INotifyPropertyChanged 5 | { 6 | public string Property2 { get; set; } 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/NotifyInBase/ClassWithNotifyInBase.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | public class ClassWithNotifyInBase : ClassParentWithProperty 4 | { 5 | [AlsoNotifyFor("Property2")] 6 | public string Property1 { get; set; } 7 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/NotifyInChild/ClassWithNotifyInChildByAttribute.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | [AddINotifyPropertyChangedInterface] 4 | public class ClassWithNotifyInChildByAttribute : ParentClass 5 | { 6 | public string Property { get; set; } 7 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/NotifyInChild/ClassWithNotifyInChildByInterface.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithNotifyInChildByInterface : ParentClass, INotifyPropertyChanged 4 | { 5 | public string Property { get; set; } 6 | public event PropertyChangedEventHandler PropertyChanged; 7 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/NotifyInChild/ParentClass.cs: -------------------------------------------------------------------------------- 1 | public class ParentClass; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/OnceRemovedINotify/ClassWithOnceRemovedINotify.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithOnceRemovedINotify : INotifyPropertyChangedChild 4 | { 5 | public string Property1 { get; set; } 6 | 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/OnceRemovedINotify/INotifyPropertyChangedChild.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public interface INotifyPropertyChangedChild : 4 | INotifyPropertyChanged; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/StructWithAttributes.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | public struct StructWithAttributes 4 | { 5 | [DependsOn("a")] 6 | [DoNotNotify] 7 | public string Property1 { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/StructWithNotify.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | public struct StructWithNotify : INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } 10 | 11 | public struct StructWithNotify : INotifyPropertyChanged 12 | { 13 | public T Property1 { get; set; } 14 | 15 | public event PropertyChangedEventHandler PropertyChanged; 16 | } 17 | 18 | [AddINotifyPropertyChangedInterface] 19 | public struct StructWithNotifyAttribute 20 | { 21 | public string Property1 { get; set; } 22 | } 23 | 24 | [AddINotifyPropertyChangedInterface] 25 | public struct StructWithNotifyAttribute 26 | { 27 | public T Property1 { get; set; } 28 | } 29 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/SupportedLibraries/ClassCaliburn.cs: -------------------------------------------------------------------------------- 1 | using Caliburn.PresentationFramework; 2 | 3 | public class ClassCaliburn : PropertyChangedBase 4 | { 5 | public string Property1 { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/SupportedLibraries/ClassCaliburnMicro.cs: -------------------------------------------------------------------------------- 1 | using Caliburn.Micro; 2 | 3 | public class ClassCaliburnMicro : 4 | PropertyChangedBase 5 | { 6 | public string Property1 { get; set; } 7 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/SupportedLibraries/ClassCaliburnOverriddenInvoker.cs: -------------------------------------------------------------------------------- 1 | using Caliburn.PresentationFramework; 2 | 3 | public class ClassCaliburnOverriddenInvoker : 4 | PropertyChangedBase 5 | { 6 | public string Property1 { get; set; } 7 | public bool OverrideCalled { get; set; } 8 | 9 | public override void NotifyOfPropertyChange(string propertyName) 10 | { 11 | OverrideCalled = true; 12 | base.NotifyOfPropertyChange(propertyName); 13 | } 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/SupportedLibraries/ClassCatel.cs: -------------------------------------------------------------------------------- 1 | using Catel.Data; 2 | 3 | public class ClassCatel : ObservableObject 4 | { 5 | public string Property1 { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/SupportedLibraries/ClassReactiveUI.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | public class ClassReactiveUI : ReactiveObject 4 | { 5 | public string Property1 { get; set; } 6 | } 7 | 8 | public class ClassReactiveUI2 : ClassReactiveUI 9 | { 10 | public string Property2 { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/SupportedLibraries/ClassTelerik.cs: -------------------------------------------------------------------------------- 1 | using Telerik.Windows.Controls; 2 | 3 | public class ClassTelerik : 4 | ViewModelBase 5 | { 6 | public string Property1 { get; set; } 7 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/TransitiveDependencies.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class TransitiveDependencies:INotifyPropertyChanged 4 | { 5 | public string My { get; set; } 6 | public string MyA => My + "A"; 7 | public string MyAB => MyA + "B"; 8 | public string MyABC => MyAB + "C"; 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | } 11 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/UsingPublicFieldThroughParameter/ClassUsingPublicFieldThroughParameter.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | public class ClassUsingPublicFieldThroughParameter 4 | { 5 | public void Write(ClassWithPublicField application) 6 | { 7 | Debug.WriteLine(application.Property1.ToString()); 8 | } 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/UsingPublicFieldThroughParameter/ClassWithPublicField.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithPublicField : 4 | INotifyPropertyChanged 5 | { 6 | public event PropertyChangedEventHandler PropertyChanged; 7 | 8 | public bool Property1; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithInitializedProperties/ClassWithAutoPropertiesInitializedInSeparateMethod.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithAutoPropertiesInitializedInSeparateMethod : ObservableTestObject 2 | { 3 | public ClassWithAutoPropertiesInitializedInSeparateMethod() 4 | { 5 | Init(); 6 | } 7 | 8 | void Init() 9 | { 10 | Property1 = "Test"; 11 | Property2 = "Test2"; 12 | } 13 | 14 | public string Property1 { get; set; } 15 | 16 | public string Property2 { get; set; } 17 | 18 | public bool IsChanged { get; set; } 19 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithInitializedProperties/ClassWithExplicitInitializedAutoProperties.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithExplicitInitializedAutoProperties : ObservableTestObject 2 | { 3 | public ClassWithExplicitInitializedAutoProperties() 4 | { 5 | Property1 = "Test"; 6 | Property2 = "Test2"; 7 | } 8 | 9 | protected ClassWithExplicitInitializedAutoProperties(string property1, string property2) 10 | { 11 | Property1 = property1; 12 | Property2 = property2; 13 | } 14 | 15 | public string Property1 { get; set; } 16 | 17 | public string Property2 { get; set; } 18 | 19 | public bool IsChanged { get; set; } 20 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithInitializedProperties/ClassWithExplicitInitializedAutoPropertiesDerivedProperDesign.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithExplicitInitializedAutoPropertiesDerivedProperDesign : ClassWithExplicitInitializedAutoProperties 2 | { 3 | public ClassWithExplicitInitializedAutoPropertiesDerivedProperDesign() 4 | : base("test", "test2") 5 | { 6 | Property3 = "test3"; 7 | } 8 | 9 | public string Property3 { get; set; } 10 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithInitializedProperties/ClassWithExplicitInitializedAutoPropertiesDerivedWeakDesign.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithExplicitInitializedAutoPropertiesDerivedWeakDesign : ClassWithExplicitInitializedAutoProperties 2 | { 3 | public ClassWithExplicitInitializedAutoPropertiesDerivedWeakDesign() 4 | { 5 | Property1 = "test"; 6 | Property2 = "test2"; 7 | Property3 = "test3"; 8 | } 9 | 10 | public string Property3 { get; set; } 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithInitializedProperties/ClassWithExplicitInitializedBackingFieldProperties.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithExplicitInitializedBackingFieldProperties : ObservableTestObject 2 | { 3 | string property1; 4 | string property2; 5 | 6 | public ClassWithExplicitInitializedBackingFieldProperties() 7 | { 8 | Property1 = "Test"; 9 | Property2 = "Test2"; 10 | } 11 | 12 | public string Property1 { 13 | get => property1; set => property1 = value; } 14 | 15 | public string Property2 { 16 | get => property2; set => property2 = value; } 17 | 18 | public bool IsChanged { get; set; } 19 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithInitializedProperties/ClassWithInlineInitializedAutoProperties.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithInlineInitializedAutoProperties : ObservableTestObject 2 | { 3 | public string Property1 { get; set; } = "Test"; 4 | 5 | public string Property2 { get; set; } = "Test2"; 6 | 7 | public bool IsChanged { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithInitializedProperties/ObservableTestObject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | using PropertyChanged; 5 | 6 | public abstract class ObservableTestObject : 7 | INotifyPropertyChanged 8 | { 9 | [DoNotNotify] 10 | public IList PropertyChangedCalls { get; } = new List(); 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | 14 | protected virtual void OnPropertyChanged(string propertyName) 15 | { 16 | PropertyChangedCalls.Add(propertyName); 17 | PropertyChanged?.Invoke(this, new(propertyName)); 18 | } 19 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithOwnIsChangedImplementation/WithOwnIsChangedImplementation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class WithOwnIsChangedImplementation : 4 | INotifyPropertyChanged 5 | { 6 | public event PropertyChangedEventHandler PropertyChanged; 7 | 8 | public bool IsChanged { get; private set; } 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyToProcess/WithOwnIsChangedImplementation/WithOwnIsChangedImplementationInherited.cs: -------------------------------------------------------------------------------- 1 | public class WithOwnIsChangedImplementationInherited : WithOwnIsChangedImplementation 2 | { 3 | public string Name { get; set; } 4 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithAttributeAndEvent/AssemblyWithAttributeAndEvent.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | true 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithAttributeAndEvent/ClassWithAttributeAndEvent.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using PropertyChanged; 3 | 4 | [AddINotifyPropertyChangedInterface] 5 | public class ClassWithAttributeAndEvent 6 | { 7 | // ReSharper disable once EventNeverSubscribedTo.Global 8 | #pragma warning disable 67 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | #pragma warning restore 67 11 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBadNamedInvoker/AssemblyWithBadNamedInvoker.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | true 6 | 7 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBadNamedInvoker/BaseClass.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class BaseClass : 4 | INotifyPropertyChanged 5 | { 6 | public event PropertyChangedEventHandler PropertyChanged; 7 | 8 | public void OnPropertyChanged2(string text1) 9 | { 10 | PropertyChanged?.Invoke(this, new(text1)); 11 | } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/AssemblyWithBase.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | true 6 | 7 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/BaseWithGenericParent/BaseClass1.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace AssemblyWithBase.BaseWithGenericParent; 4 | 5 | public class BaseClass1 : 6 | INotifyPropertyChanged { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | public virtual void OnPropertyChanged(string propertyName) 9 | { 10 | PropertyChanged?.Invoke(this, new(propertyName)); 11 | } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/BaseWithGenericParent/BaseClass2.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.BaseWithGenericParent; 2 | 3 | public class BaseClass2 : BaseClass1; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/DirectGeneric/BaseClass.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace AssemblyWithBase.DirectGeneric; 4 | 5 | public class BaseClass : 6 | INotifyPropertyChanged { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | public virtual void OnPropertyChanged(string propertyName) 9 | { 10 | PropertyChanged?.Invoke(this, new(propertyName)); 11 | } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/GenericFromAbove/BaseClass1.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.GenericFromAbove; 2 | 3 | public class BaseClass1; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/GenericFromAbove/BaseClass2.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace AssemblyWithBase.GenericFromAbove; 4 | 5 | public class BaseClass2 : BaseClass1; 6 | 7 | public class BaseClass3 : BaseClass2, INotifyPropertyChanged 8 | { 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | public virtual void OnPropertyChanged(string propertyName) 11 | { 12 | PropertyChanged?.Invoke(this, new(propertyName)); 13 | } 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/GenericMiddle/BaseClassWithGenericMiddle.cs: -------------------------------------------------------------------------------- 1 | public class BaseClassWithGenericMiddle : BaseClassWithGenericMiddleBase; 2 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/GenericMiddle/BaseClassWithGenericMiddleBase.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class BaseClassWithGenericMiddleBase : INotifyPropertyChanged 4 | { 5 | public event PropertyChangedEventHandler PropertyChanged; 6 | 7 | public virtual void OnPropertyChanged(string propertyName) 8 | { 9 | PropertyChanged?.Invoke(this, new(propertyName)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/MultiTypes/BaseClass1.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace AssemblyWithBase.MultiTypes; 4 | 5 | public class BaseClass1 : 6 | INotifyPropertyChanged { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | public virtual void OnPropertyChanged(string propertyName) 9 | { 10 | PropertyChanged?.Invoke(this, new(propertyName)); 11 | } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/MultiTypes/BaseClass2.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.MultiTypes; 2 | 3 | public class BaseClass2 : BaseClass1; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/Simple/BaseClass.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace AssemblyWithBase.Simple; 4 | 5 | public class BaseClass : 6 | INotifyPropertyChanged { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | public virtual void OnPropertyChanged(string text1) 10 | { 11 | PropertyChanged?.Invoke(this, new(text1)); 12 | } 13 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/Simple/BaseClassWithVirtualProperty.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.Simple; 2 | 3 | using System.ComponentModel; 4 | 5 | public class BaseClassWithVirtualProperty : 6 | INotifyPropertyChanged { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | public virtual string Property1 { get; set; } 10 | 11 | public virtual void OnPropertyChanged(string text1) 12 | { 13 | PropertyChanged?.Invoke(this, new(text1)); 14 | } 15 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEquals/BaseClass.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEquals; 2 | 3 | public class BaseClass 4 | { 5 | static bool staticEqualsCalled; 6 | public bool StaticEqualsCalled 7 | { 8 | get => staticEqualsCalled; 9 | set => staticEqualsCalled = value; 10 | } 11 | 12 | public static bool Equals(BaseClass first, BaseClass second) 13 | { 14 | staticEqualsCalled = true; 15 | 16 | if (ReferenceEquals(first, second)) 17 | { 18 | return true; 19 | } 20 | 21 | if (first == null || second == null) 22 | { 23 | return false; 24 | } 25 | 26 | return first.Equals(second); 27 | } 28 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEqualsGenericParent/BaseClass.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEqualsGenericParent; 2 | 3 | public class BaseClass 4 | { 5 | static bool staticEqualsCalled; 6 | public bool StaticEqualsCalled 7 | { 8 | get => staticEqualsCalled; 9 | set => staticEqualsCalled = value; 10 | } 11 | 12 | public static bool Equals(BaseClass first, BaseClass second) 13 | { 14 | staticEqualsCalled = true; 15 | 16 | if (ReferenceEquals(first, second)) 17 | { 18 | return true; 19 | } 20 | 21 | if (first == null || second == null) 22 | { 23 | return false; 24 | } 25 | 26 | return first.Equals(second); 27 | } 28 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEqualsGenericParent/BaseClass2.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEqualsGenericParent; 2 | 3 | public class BaseClass2 : BaseClass 4 | { 5 | public T SomeProperty { get; set; } 6 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEqualsGenericParent/BaseClass3.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEqualsGenericParent; 2 | 3 | public class BaseClass3 : BaseClass2; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEqualsGenericParent/ClassUsingBase.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEqualsGenericParent; 2 | 3 | public class ClassUsingBaseEquals : BaseClass; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEqualsGenericParent/ClassWithOwnEquals.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEqualsGenericParent; 2 | 3 | public class ClassWithOwnEquals : BaseClass 4 | { 5 | static bool childStaticEqualsCalled; 6 | 7 | public bool ChildStaticEqualsCalled 8 | { 9 | get => childStaticEqualsCalled; 10 | set => childStaticEqualsCalled = value; 11 | } 12 | 13 | public static bool Equals(ClassWithOwnEquals first, ClassWithOwnEquals second) 14 | { 15 | childStaticEqualsCalled = true; 16 | 17 | if (ReferenceEquals(first, second)) 18 | { 19 | return true; 20 | } 21 | 22 | if (first == null || second == null) 23 | { 24 | return false; 25 | } 26 | 27 | return first.Equals(second); 28 | } 29 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEqualsGenericParent/ClassWithTwoBaseClasses1.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEqualsGenericParent; 2 | 3 | public class ClassWithTwoBaseClasses1 : BaseClass2; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBase/StaticEqualsGenericParent/ClassWithTwoBaseClasses2.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBase.StaticEqualsGenericParent; 2 | 3 | public class ClassWithTwoBaseClasses2 : BaseClass3; -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/AssemblyWithBaseInDifferentModule.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | true 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/BaseWithGenericParent/ChildClass.cs: -------------------------------------------------------------------------------- 1 | using AssemblyWithBase.BaseWithGenericParent; 2 | 3 | namespace AssemblyWithBaseInDifferentModule.BaseWithGenericParent; 4 | 5 | public class ChildClass : BaseClass2 6 | { 7 | public string Property1 { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/BaseWithGenericProperty/Class.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using AssemblyWithBase.BaseWithEquals; 4 | 5 | namespace AssemblyWithBaseInDifferentModule.BaseWithGenericProperty; 6 | 7 | public class Class : 8 | INotifyPropertyChanged { 9 | string property1; 10 | 11 | public string Property1 12 | { 13 | get => property1; 14 | set 15 | { 16 | property1 = value; 17 | Property2 = new(); 18 | } 19 | } 20 | 21 | public BaseClass1 Property2 { get; set; } 22 | 23 | public event PropertyChangedEventHandler PropertyChanged; 24 | 25 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 26 | { 27 | PropertyChanged?.Invoke(this, new(propertyName)); 28 | } 29 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/DirectGeneric/ChildClass.cs: -------------------------------------------------------------------------------- 1 | using AssemblyWithBase.DirectGeneric; 2 | 3 | namespace AssemblyWithBaseInDifferentModule.DirectGeneric; 4 | 5 | public class ChildClass : BaseClass 6 | { 7 | public string Property1 { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/GenericFromAbove/ChildClass.cs: -------------------------------------------------------------------------------- 1 | using AssemblyWithBase.GenericFromAbove; 2 | 3 | namespace AssemblyWithBaseInDifferentModule.GenericFromAbove; 4 | 5 | public class ChildClass : BaseClass3 6 | { 7 | public string Property1 { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/GenericMiddle/ClassWithGenericMiddleChildInDifferentModule.cs: -------------------------------------------------------------------------------- 1 | public class ClassWithGenericMiddleChildInDifferentModule : BaseClassWithGenericMiddle 2 | { 3 | public int Property { get; set; } 4 | } 5 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/Hierarchy/ChildClass.cs: -------------------------------------------------------------------------------- 1 | namespace AssemblyWithBaseInDifferentModule.Hierarchy; 2 | 3 | using AssemblyWithBase.StaticEquals; 4 | 5 | public class ChildClass : StaticEquals 6 | { 7 | string property1; 8 | public string Property1 9 | { 10 | get => property1; 11 | set 12 | { 13 | property1 = value; 14 | Property2 = new(); 15 | } 16 | } 17 | 18 | public BaseClass Property2 { get; set; } 19 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/Hierarchy/StaticEquals.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace AssemblyWithBaseInDifferentModule.Hierarchy; 5 | 6 | public class StaticEquals : 7 | INotifyPropertyChanged 8 | { 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | 11 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 12 | { 13 | PropertyChanged?.Invoke(this, new(propertyName)); 14 | } 15 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/MultiTypes/ChildClass.cs: -------------------------------------------------------------------------------- 1 | using AssemblyWithBase.MultiTypes; 2 | 3 | namespace AssemblyWithBaseInDifferentModule.MultiTypes; 4 | 5 | public class ChildClass : BaseClass2 6 | { 7 | public string Property1 { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/Simple/ChildClass.cs: -------------------------------------------------------------------------------- 1 | using AssemblyWithBase.Simple; 2 | 3 | namespace AssemblyWithBaseInDifferentModule.Simple; 4 | 5 | public class ChildClass : BaseClass 6 | { 7 | public string Property1 { get; set; } 8 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/StaticEquals/StaticEquals.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using AssemblyWithBase.StaticEquals; 4 | 5 | namespace AssemblyWithBaseInDifferentModule.StaticEquals; 6 | 7 | public class StaticEquals : 8 | INotifyPropertyChanged { 9 | string property1; 10 | public string Property1 11 | { 12 | get => property1; 13 | set 14 | { 15 | property1 = value; 16 | Property2 = new(); 17 | } 18 | } 19 | 20 | public BaseClass Property2 { get; set; } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 24 | { 25 | PropertyChanged?.Invoke(this, new(propertyName)); 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/StaticEqualsGenericParent/ArgsMapping1.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using AssemblyWithBase.StaticEqualsGenericParent; 4 | 5 | namespace AssemblyWithBaseInDifferentModule.StaticEqualsGenericParent; 6 | 7 | public class ArgsMapping1 : 8 | INotifyPropertyChanged { 9 | string property1; 10 | public string Property1 11 | { 12 | get => property1; 13 | set 14 | { 15 | property1 = value; 16 | Property2 = new(); 17 | } 18 | } 19 | 20 | public ClassWithTwoBaseClasses1 Property2 { get; set; } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 24 | { 25 | PropertyChanged?.Invoke(this, new(propertyName)); 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/StaticEqualsGenericParent/ArgsMapping2.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using AssemblyWithBase.StaticEqualsGenericParent; 4 | 5 | namespace AssemblyWithBaseInDifferentModule.StaticEqualsGenericParent; 6 | 7 | public class ArgsMapping2 : 8 | INotifyPropertyChanged { 9 | string property1; 10 | public string Property1 11 | { 12 | get => property1; 13 | set 14 | { 15 | property1 = value; 16 | Property2 = new(); 17 | } 18 | } 19 | 20 | public ClassWithTwoBaseClasses2 Property2 { get; set; } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 24 | { 25 | PropertyChanged?.Invoke(this, new(propertyName)); 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/StaticEqualsGenericParent/OwnStaticEquals.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using AssemblyWithBase.StaticEqualsGenericParent; 4 | 5 | namespace AssemblyWithBaseInDifferentModule.StaticEqualsGenericParent; 6 | 7 | public class OwnStaticEquals : 8 | INotifyPropertyChanged { 9 | string property1; 10 | public string Property1 11 | { 12 | get => property1; 13 | set 14 | { 15 | property1 = value; 16 | Property2 = new(); 17 | } 18 | } 19 | 20 | public ClassWithOwnEquals Property2 { get; set; } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 24 | { 25 | PropertyChanged?.Invoke(this, new(propertyName)); 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/StaticEqualsGenericParent/StaticEquals.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using AssemblyWithBase.StaticEqualsGenericParent; 4 | 5 | namespace AssemblyWithBaseInDifferentModule.StaticEqualsGenericParent; 6 | 7 | public class StaticEquals : 8 | INotifyPropertyChanged { 9 | string property1; 10 | public string Property1 11 | { 12 | get => property1; 13 | set 14 | { 15 | property1 = value; 16 | Property2 = new(); 17 | } 18 | } 19 | 20 | public BaseClass Property2 { get; set; } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 24 | { 25 | PropertyChanged?.Invoke(this, new(propertyName)); 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBaseInDifferentModule/StaticEqualsGenericParent/StaticEqualsOnBase.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using AssemblyWithBase.StaticEqualsGenericParent; 4 | 5 | namespace AssemblyWithBaseInDifferentModule.StaticEqualsGenericParent; 6 | 7 | public class StaticEqualsOnBase : 8 | INotifyPropertyChanged { 9 | string property1; 10 | public string Property1 11 | { 12 | get => property1; 13 | set 14 | { 15 | property1 = value; 16 | Property2 = new(); 17 | } 18 | } 19 | 20 | public ClassUsingBaseEquals Property2 { get; set; } 21 | 22 | public event PropertyChangedEventHandler PropertyChanged; 23 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 24 | { 25 | PropertyChanged?.Invoke(this, new(propertyName)); 26 | } 27 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBeforeAfterInterceptor/AssemblyWithBeforeAfterInterceptor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067 6 | true 7 | 8 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBeforeAfterInterceptor/ClassToTest.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassToTest : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBeforeAfterInterceptor/PropertyNotificationInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public static class PropertyChangedNotificationInterceptor 4 | { 5 | public static void Intercept(object target, Action action, string propertyName, object before, object after) 6 | { 7 | action(); 8 | InterceptCalled = true; 9 | } 10 | 11 | public static bool InterceptCalled { get; set; } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBlockingClass/AssemblyWithBlockingClass.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | true 6 | 7 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithBlockingClass/Classes.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.ComponentModel; 3 | 4 | public class A : 5 | ObservableCollection; 6 | 7 | public class B : 8 | INotifyPropertyChanged 9 | { 10 | public string Property1 { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | 14 | public void OnPropertyChanged(string propertyName) 15 | { 16 | PropertyChanged(this, new(propertyName)); 17 | } 18 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithDisabledInjectOnPropertyNameChanged/AssemblyWithDisabledInjectOnPropertyNameChanged.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067 6 | true 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithDisabledInjectOnPropertyNameChanged/ClassWithConfiguredOnPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Diagnostics.CodeAnalysis; 3 | using PropertyChanged; 4 | 5 | [SuppressMessage("ReSharper", "NotAccessedField.Global")] 6 | public class ClassWithConfiguredOnPropertyChanged : 7 | INotifyPropertyChanged 8 | { 9 | public int OnProperty1ChangedCallCount; 10 | 11 | [OnChangedMethod(nameof(OnProperty1Changed))] 12 | public string Property1 { get; set; } 13 | 14 | public event PropertyChangedEventHandler PropertyChanged; 15 | 16 | void OnProperty1Changed() 17 | { 18 | ++OnProperty1ChangedCallCount; 19 | } 20 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithDisabledInjectOnPropertyNameChanged/ClassWithOnPropertyChangedMethod.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | [SuppressMessage("ReSharper", "NotAccessedField.Global")] 5 | public class ClassWithOnPropertyChangedMethod : 6 | INotifyPropertyChanged 7 | { 8 | public int OnProperty1ChangedCallCount; 9 | 10 | public string Property1 { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | 14 | [SuppressMessage("ReSharper", "UnusedMember.Local")] 15 | void OnProperty1Changed() 16 | { 17 | ++OnProperty1ChangedCallCount; 18 | } 19 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithDisabledIsChangedProperty/AssemblyWithDisabledIsChangedProperty.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067 6 | true 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithDisabledIsChangedProperty/IsChangedClassToTest.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | [SuppressMessage("ReSharper", "NotAccessedField.Global")] 5 | public class IsChangedClassToTest : 6 | INotifyPropertyChanged 7 | { 8 | public string Property1 { get; set; } 9 | 10 | public bool IsChanged { get; set; } 11 | 12 | public event PropertyChangedEventHandler PropertyChanged; 13 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithDisabledTriggerDependentProperties/AssemblyWithDisabledTriggerDependentProperties.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067 6 | true 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithDisabledTriggerDependentProperties/DependentPropertiesClassToTest.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | [SuppressMessage("ReSharper", "NotAccessedField.Global")] 5 | public class DependentPropertiesClassToTest : 6 | INotifyPropertyChanged 7 | { 8 | public int OnProperty1ChangedCallCount; 9 | public int OnProperty2ChangedCallCount; 10 | 11 | public string Property1 { get; set; } 12 | public string Property2 => $"{Property1}"; 13 | 14 | public event PropertyChangedEventHandler PropertyChanged; 15 | 16 | public virtual void OnPropertyChanged(string propertyName) 17 | { 18 | switch(propertyName) 19 | { 20 | case nameof(Property1): 21 | ++OnProperty1ChangedCallCount; 22 | break; 23 | case nameof(Property2): 24 | ++OnProperty2ChangedCallCount; 25 | break; 26 | } 27 | 28 | PropertyChanged?.Invoke(this, new(propertyName)); 29 | } 30 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithExternalInheritance/AssemblyWithExternalInheritance.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net48;net6.0 4 | 0067;0649 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithInheritance/AssemblyWithInheritance.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net48;net6.0 4 | 0067;0649 5 | true 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithInterceptor/AssemblyWithInterceptor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067 6 | true 7 | 8 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithInterceptor/ClassToTest.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassToTest : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithInterceptor/PropertyNotificationInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public static class PropertyChangedNotificationInterceptor 4 | { 5 | public static void Intercept(object target, Action action, string propertyName) 6 | { 7 | action(); 8 | InterceptCalled = true; 9 | } 10 | 11 | public static bool InterceptCalled { get; set; } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithNonVoidOnPropertyNameChanged/AssemblyWithNonVoidOnPropertyNameChanged.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067 6 | true 7 | 8 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithNonVoidOnPropertyNameChanged/ClassWithNonVoidOnPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithNonVoidOnPropertyChanged : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | public int OnProperty1Changed() 11 | { 12 | return 0; 13 | } 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithStackOverflow/AssemblyWithStackOverflow.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | true 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithStackOverflow/BaseClass.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class BaseClass : 4 | INotifyPropertyChanged 5 | { 6 | public virtual string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | protected void OnPropertyChanged(string propertyName, object before, object after) 11 | { 12 | PropertyChanged?.Invoke(this, new(propertyName)); 13 | } 14 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithStackOverflow/ChildClass.cs: -------------------------------------------------------------------------------- 1 | public class ChildClassWithOverflow : BaseClass 2 | { 3 | public override string Property1 { 4 | get 5 | { 6 | if (string.IsNullOrEmpty(base.Property1)) 7 | { 8 | base.Property1 = "test"; 9 | } 10 | 11 | return base.Property1; 12 | } 13 | 14 | set => base.Property1 = value; } 15 | } 16 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithStackOverflow/ChildWithBaseInDifferentAssembly.cs: -------------------------------------------------------------------------------- 1 |  using AssemblyWithBase.Simple; 2 | 3 | public class ChildWithBaseInDifferentAssembly : BaseClassWithVirtualProperty 4 | { 5 | public override string Property1 { 6 | get 7 | { 8 | if (string.IsNullOrEmpty(base.Property1)) 9 | { 10 | base.Property1 = "test"; 11 | } 12 | 13 | return base.Property1; 14 | } 15 | 16 | set => base.Property1 = value; } 17 | } 18 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithStackOverflow/ClassWithStackOverflow.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithStackOverflow : 4 | INotifyPropertyChanged 5 | { 6 | string name; 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | public string Name 11 | { 12 | get 13 | { 14 | if (string.IsNullOrEmpty(name)) 15 | { 16 | Name = "test"; 17 | } 18 | 19 | return Name; 20 | } 21 | set => name = value; 22 | } 23 | 24 | public string ValidName { get; set; } 25 | 26 | protected void OnPropertyChanged(string propertyName, object before, object after) 27 | { 28 | PropertyChanged?.Invoke(this, new(propertyName)); 29 | } 30 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithStaticOnPropertyNameChanged/AssemblyWithStaticOnPropertyNameChanged.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net48;net6.0 4 | 0067 5 | true 6 | 7 | 8 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithStaticOnPropertyNameChanged/ClassWithNonVoidOnPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class ClassWithStaticOnPropertyChanged : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | 10 | public static void OnProperty1Changed() 11 | { 12 | } 13 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithTypeFilter/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | [assembly: FilterType("PropertyChangedTest.")] 4 | [assembly: FilterType("PropertyChangedTestWithDifferentNamespace.")] -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithTypeFilter/AssemblyWithTypeFilter.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48;net6.0 5 | 0067 6 | true 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithTypeFilter/PropertyChangedNotificationInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public static class PropertyChangedNotificationInterceptor 4 | { 5 | public static void Intercept(object target, Action action, string propertyName) 6 | { 7 | action(); 8 | InterceptCalled = true; 9 | } 10 | 11 | public static bool InterceptCalled { get; set; } 12 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithTypeFilter/TestClassExclude.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | public class TestClassExclude : 4 | INotifyPropertyChanged 5 | { 6 | public string Property1 { get; set; } 7 | 8 | public event PropertyChangedEventHandler PropertyChanged; 9 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithTypeFilter/TestClassInclude.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace PropertyChangedTest; 4 | 5 | public class TestClassInclude : 6 | INotifyPropertyChanged { 7 | public string Property1 { get; set; } 8 | 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | } -------------------------------------------------------------------------------- /TestAssemblies/AssemblyWithTypeFilter/TestClassIncludeAlso.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace PropertyChangedTestWithDifferentNamespace; 4 | 5 | public class TestClassIncludeAlso : 6 | INotifyPropertyChanged { 7 | public string Property1 { get; set; } 8 | 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | } -------------------------------------------------------------------------------- /Tests/AssemblyExplicitPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyExplicitPropertyChanged 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var weaver = new ModuleWeaver(); 7 | var weavingException = Assert.Throws(() => 8 | { 9 | weaver.ExecuteTestRun("AssemblyExplicitPropertyChanged.dll"); 10 | }); 11 | Assert.Equal("Could not inject EventInvoker method on type 'ClassExplicitPropertyChanged'. It is possible you are inheriting from a base class and have not correctly set 'EventInvokerNames' or you are using a explicit PropertyChanged event and the event field is not visible to this instance. Either correct 'EventInvokerNames' or implement your own EventInvoker on this class. If you want to suppress this place a [DoNotNotifyAttribute] on ClassExplicitPropertyChanged.", weavingException.Message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Tests/AssemblyWithAttributeAndEventTests.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyWithAttributeAndEventTests 2 | { 3 | [Fact] 4 | public void WithAttributeAndEvent() 5 | { 6 | var task = new ModuleWeaver(); 7 | var exception = Assert.Throws(() => task.ExecuteTestRun("AssemblyWithAttributeAndEvent.dll")); 8 | Assert.Equal("The type 'ClassWithAttributeAndEvent' already has a PropertyChanged event. If type has a [AddINotifyPropertyChangedInterfaceAttribute] then the PropertyChanged event can be removed.", exception.Message); 9 | } 10 | } -------------------------------------------------------------------------------- /Tests/AssemblyWithBadNamedInvokerTests.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyWithBadNamedInvokerTests 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var task = new ModuleWeaver(); 7 | var exception = Assert.Throws(() => task.ExecuteTestRun("AssemblyInheritingBadNamedInvoker.dll")); 8 | Assert.Equal("Could not inject EventInvoker method on type 'ChildClass'. It is possible you are inheriting from a base class and have not correctly set 'EventInvokerNames' or you are using a explicit PropertyChanged event and the event field is not visible to this instance. Either correct 'EventInvokerNames' or implement your own EventInvoker on this class. If you want to suppress this place a [DoNotNotifyAttribute] on ChildClass.", exception.Message); 9 | } 10 | } -------------------------------------------------------------------------------- /Tests/AssemblyWithBlockingClassTests.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyWithBlockingClassTests 2 | { 3 | [Fact] 4 | public void TestClassIsNotBlocked() 5 | { 6 | var task = new ModuleWeaver(); 7 | var testResult = task.ExecuteTestRun( 8 | "AssemblyWithBlockingClass.dll", 9 | ignoreCodes: ["0x80131869"]); 10 | var instance = testResult.GetInstance("B"); 11 | EventTester.TestProperty(instance, false); 12 | } 13 | } -------------------------------------------------------------------------------- /Tests/AssemblyWithDisabledInjectOnPropertyNameChangedTests.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyWithDisabledInjectOnPropertyNameChangedTests 2 | { 3 | static TestResult testResult; 4 | 5 | static AssemblyWithDisabledInjectOnPropertyNameChangedTests() 6 | { 7 | var task = new ModuleWeaver 8 | { 9 | InjectOnPropertyNameChanged = false 10 | }; 11 | testResult = task.ExecuteTestRun( 12 | "AssemblyWithDisabledInjectOnPropertyNameChanged.dll", 13 | ignoreCodes: ["0x80131869"]); 14 | } 15 | 16 | [Fact] 17 | public void DefaultMethodCallsAreNotInjected() 18 | { 19 | var instance = testResult.GetInstance(nameof(ClassWithOnPropertyChangedMethod)); 20 | instance.Property1 = "foo"; 21 | 22 | Assert.Equal(0, instance.OnProperty1ChangedCallCount); 23 | } 24 | 25 | [Fact] 26 | public void CustomMethodCallsAreInjected() 27 | { 28 | var instance = testResult.GetInstance(nameof(ClassWithConfiguredOnPropertyChanged)); 29 | instance.Property1 = "foo"; 30 | 31 | Assert.Equal(1, instance.OnProperty1ChangedCallCount); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/AssemblyWithDisabledIsChangedPropertyTests.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyWithDisabledIsChangedPropertyTests 2 | { 3 | static TestResult testResult; 4 | 5 | static AssemblyWithDisabledIsChangedPropertyTests() 6 | { 7 | var task = new ModuleWeaver 8 | { 9 | EnableIsChangedProperty = false 10 | }; 11 | testResult = task.ExecuteTestRun( 12 | "AssemblyWithDisabledIsChangedProperty.dll", 13 | ignoreCodes: ["0x80131869"]); 14 | } 15 | 16 | [Fact] 17 | public void DisabledIsChangedProperty() 18 | { 19 | var instance = testResult.GetInstance(nameof(IsChangedClassToTest)); 20 | instance.Property1 = "foo"; 21 | 22 | Assert.True(instance.IsChanged != true); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Tests/AssemblyWithDisabledTriggerDependentPropertiesTests.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyWithDisabledTriggerDependentPropertiesTests 2 | { 3 | static TestResult testResult; 4 | 5 | static AssemblyWithDisabledTriggerDependentPropertiesTests() 6 | { 7 | var task = new ModuleWeaver 8 | { 9 | TriggerDependentProperties = false 10 | }; 11 | testResult = task.ExecuteTestRun( 12 | "AssemblyWithDisabledTriggerDependentProperties.dll", 13 | ignoreCodes: ["0x80131869"]); 14 | } 15 | 16 | [Fact] 17 | public void TriggerDependentPropertiesDisabled() 18 | { 19 | var instance = testResult.GetInstance(nameof(DependentPropertiesClassToTest)); 20 | instance.Property1 = "foo"; 21 | 22 | Assert.Equal(1, instance.OnProperty1ChangedCallCount); 23 | Assert.Equal(0, instance.OnProperty2ChangedCallCount); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/AssemblyWithNonVoidOnPropertyChangedTests.Simple.verified.txt: -------------------------------------------------------------------------------- 1 | The type ClassWithNonVoidOnPropertyChanged has a On_PropertyName_Changed method (OnProperty1Changed) that has a non void return value. Ensure the return type void. You can suppress this warning with [SuppressPropertyChangedWarnings]. -------------------------------------------------------------------------------- /Tests/AssemblyWithNonVoidOnPropertyChangedTests.cs: -------------------------------------------------------------------------------- 1 | public class AssemblyWithNonVoidOnPropertyChangedTests 2 | { 3 | [Fact] 4 | public Task Simple() 5 | { 6 | var task = new ModuleWeaver(); 7 | var result = task.ExecuteTestRun( 8 | "AssemblyWithNonVoidOnPropertyNameChanged.dll", 9 | ignoreCodes: ["0x80131869"]); 10 | return Verifier.Verify(result.Warnings.Single().Text); 11 | } 12 | } -------------------------------------------------------------------------------- /Tests/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | static class Extensions 4 | { 5 | public static bool ContainsWholeWord(this string str, string word) 6 | => Regex.IsMatch(str, $@"\b{Regex.Escape(word)}\b", RegexOptions.CultureInvariant); 7 | } 8 | -------------------------------------------------------------------------------- /Tests/FSharpTest.cs: -------------------------------------------------------------------------------- 1 | public class FSharpTest 2 | { 3 | TestResult testResult; 4 | 5 | public FSharpTest() 6 | { 7 | var weaver = new ModuleWeaver(); 8 | testResult = weaver.ExecuteTestRun("AssemblyFSharp.dll", runPeVerify: false); 9 | } 10 | 11 | [Fact] 12 | public void SimpleClass() 13 | { 14 | var instance = testResult.GetInstance("Namespace.ClassWithProperties"); 15 | EventTester.TestProperty(instance, false); 16 | } 17 | 18 | [Fact] 19 | public void WithNoOnPropertyChanged() 20 | { 21 | var instance = testResult.GetInstance("Namespace.ClassWithNoOnPropertyChanged"); 22 | EventTester.TestProperty(instance, false); 23 | } 24 | } -------------------------------------------------------------------------------- /Tests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | global using System.Linq; 4 | global using System.Threading.Tasks; 5 | global using Fody; 6 | global using VerifyXunit; 7 | global using Xunit; -------------------------------------------------------------------------------- /Tests/IlGeneratedByDependencyReaderTests/WithAutoProperties.cs: -------------------------------------------------------------------------------- 1 | public class WithAutoProperties 2 | { 3 | //TODO: add test for abstract 4 | 5 | [Fact] 6 | public void Run() 7 | { 8 | var typeDefinition = DefinitionFinder.FindType(); 9 | var node = new TypeNode 10 | { 11 | TypeDefinition = typeDefinition, 12 | Mappings = ModuleWeaver.GetMappings(typeDefinition).ToList() 13 | }; 14 | new IlGeneratedByDependencyReader(node).Process(); 15 | Assert.Equal(2, node.PropertyDependencies.Count); 16 | var first = node.PropertyDependencies[0]; 17 | Assert.Equal("FullName", first.ShouldAlsoNotifyFor.Name); 18 | Assert.Equal("GivenNames", first.WhenPropertyIsSet.Name); 19 | var second = node.PropertyDependencies[1]; 20 | Assert.Equal("FullName", second.ShouldAlsoNotifyFor.Name); 21 | Assert.Equal("FamilyName", second.WhenPropertyIsSet.Name); 22 | } 23 | 24 | public class Person 25 | { 26 | public string GivenNames { get; set; } 27 | public string FamilyName { get; set; } 28 | public string FullName => $"{GivenNames} {FamilyName}"; 29 | } 30 | } -------------------------------------------------------------------------------- /Tests/IlGeneratedByDependencyReaderTests/WithDoNotNotifyProperty.cs: -------------------------------------------------------------------------------- 1 | using PropertyChanged; 2 | 3 | public class WithDoNotNotifyProperty 4 | { 5 | [Fact] 6 | public void Run() 7 | { 8 | var typeDefinition = DefinitionFinder.FindType(); 9 | var node = new TypeNode 10 | { 11 | TypeDefinition = typeDefinition, 12 | Mappings = ModuleWeaver.GetMappings(typeDefinition).ToList() 13 | }; 14 | new IlGeneratedByDependencyReader(node).Process(); 15 | Assert.Empty(node.PropertyDependencies); 16 | } 17 | 18 | public class Person 19 | { 20 | public string GivenNames { get; set; } 21 | public string FamilyName { get; set; } 22 | [DoNotNotify] 23 | public string FullName => $"{GivenNames} {FamilyName}"; 24 | } 25 | } -------------------------------------------------------------------------------- /Tests/IlGeneratedByDependencyReaderTests/WithGenericAutoProperties.cs: -------------------------------------------------------------------------------- 1 | public class WithGenericAutoProperties 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var typeDefinition = DefinitionFinder.FindType>(); 7 | var node = new TypeNode 8 | { 9 | TypeDefinition = typeDefinition, 10 | Mappings = ModuleWeaver.GetMappings(typeDefinition).ToList() 11 | }; 12 | new IlGeneratedByDependencyReader(node).Process(); 13 | var first = node.PropertyDependencies[0]; 14 | Assert.Equal("FullName", first.ShouldAlsoNotifyFor.Name); 15 | Assert.Equal("GivenNames", first.WhenPropertyIsSet.Name); 16 | var second = node.PropertyDependencies[1]; 17 | Assert.Equal("FullName", second.ShouldAlsoNotifyFor.Name); 18 | Assert.Equal("FamilyName", second.WhenPropertyIsSet.Name); 19 | } 20 | 21 | public class Person 22 | { 23 | public string GivenNames { get; set; } 24 | public string FamilyName { get; set; } 25 | public string FullName => $"{GivenNames} {FamilyName}"; 26 | } 27 | } -------------------------------------------------------------------------------- /Tests/IlGeneratedByDependencyReaderTests/WithGenericFields.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | // ReSharper disable UnusedMember.Global 4 | public class WithGenericFields 5 | { 6 | [Fact] 7 | public void Run() 8 | { 9 | var typeDefinition = DefinitionFinder.FindType>(); 10 | var node = new TypeNode 11 | { 12 | TypeDefinition = typeDefinition, 13 | Mappings = ModuleWeaver.GetMappings(typeDefinition).ToList() 14 | }; 15 | 16 | new IlGeneratedByDependencyReader(node).Process(); 17 | Assert.Equal("FullName", node.PropertyDependencies[0].ShouldAlsoNotifyFor.Name); 18 | Assert.Equal("GivenNames", node.PropertyDependencies[0].WhenPropertyIsSet.Name); 19 | Assert.Equal("FullName", node.PropertyDependencies[1].ShouldAlsoNotifyFor.Name); 20 | Assert.Equal("FamilyName", node.PropertyDependencies[1].WhenPropertyIsSet.Name); 21 | } 22 | 23 | public class Person 24 | { 25 | public string GivenNames { get; set; } 26 | 27 | public string FamilyName { get; set; } 28 | 29 | public string FullName => $"{GivenNames} {FamilyName}"; 30 | } 31 | } -------------------------------------------------------------------------------- /Tests/IlGeneratedByDependencyReaderTests/WithLambda.cs: -------------------------------------------------------------------------------- 1 | public class WithLambda 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var typeDefinition = DefinitionFinder.FindType(); 7 | var node = new TypeNode 8 | { 9 | TypeDefinition = typeDefinition, 10 | Mappings = ModuleWeaver.GetMappings(typeDefinition).ToList() 11 | }; 12 | new IlGeneratedByDependencyReader(node).Process(); 13 | Assert.Single(node.PropertyDependencies); 14 | Assert.Equal("PropertyWithLambda", node.PropertyDependencies[0].ShouldAlsoNotifyFor.Name); 15 | Assert.Equal("Property1", node.PropertyDependencies[0].WhenPropertyIsSet.Name); 16 | } 17 | 18 | public class TestClass 19 | { 20 | public double PropertyWithLambda 21 | { 22 | get 23 | { 24 | var dashArray = new[] { 5D }.Select(a => a / Property1); 25 | return dashArray.First(); 26 | } 27 | } 28 | 29 | public double Property1 { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /Tests/IlGeneratedByDependencyReaderTests/WithVirtualAutoProperties.cs: -------------------------------------------------------------------------------- 1 | public class WithVirtualAutoProperties 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var typeDefinition = DefinitionFinder.FindType(); 7 | var node = new TypeNode 8 | { 9 | TypeDefinition = typeDefinition, 10 | Mappings = ModuleWeaver.GetMappings(typeDefinition).ToList() 11 | }; 12 | new IlGeneratedByDependencyReader(node).Process(); 13 | var first = node.PropertyDependencies[0]; 14 | Assert.Single(node.PropertyDependencies); 15 | Assert.Equal("FullName", first.ShouldAlsoNotifyFor.Name); 16 | Assert.Equal("GivenNames", first.WhenPropertyIsSet.Name); 17 | } 18 | 19 | public class Person 20 | { 21 | public virtual string GivenNames { get; set; } 22 | public virtual string FullName => GivenNames; 23 | } 24 | } -------------------------------------------------------------------------------- /Tests/InjectOnPropertyNameChangedTests.ModuleWeaver_WhenInjectOnPropertyNameChangedIsTrue_WarnsForNonVoidMethods.verified.txt: -------------------------------------------------------------------------------- 1 | The type ClassWithNonVoidOnPropertyChanged has a On_PropertyName_Changed method (OnProperty1Changed) that has a non void return value. Ensure the return type void. You can suppress this warning with [SuppressPropertyChangedWarnings]. -------------------------------------------------------------------------------- /Tests/InjectOnPropertyNameChangedTests.ModuleWeaver_WhenInjectOnPropertyNameChangedIsTrue_WarnsForStaticMethods.verified.txt: -------------------------------------------------------------------------------- 1 | The type ClassWithStaticOnPropertyChanged has a On_PropertyName_Changed method (OnProperty1Changed) which is static. You can suppress this warning with [SuppressPropertyChangedWarnings]. -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderAutoPropertiesAndDodgyField.cs: -------------------------------------------------------------------------------- 1 | public class MappingFinderAutoPropertiesAndDodgyField 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 7 | Assert.Equal("k__BackingField", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1").FieldDefinition.Name); 8 | Assert.Equal("k__BackingField", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property2").FieldDefinition.Name); 9 | } 10 | 11 | public class ClassWithAutoPropertiesAndDodgyField 12 | { 13 | #pragma warning disable 169 14 | string _property2; 15 | #pragma warning restore 169 16 | public string Property1 { get; set; } 17 | public string Property2 { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderInnerClass.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 649 2 | 3 | 4 | public class MappingFinderInnerClass 5 | { 6 | [Fact] 7 | public void Run() 8 | { 9 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 10 | Assert.Null(memberMappings.Single().FieldDefinition); 11 | } 12 | 13 | public class Model 14 | { 15 | InnerClass innerClass; 16 | public string Property1 17 | { 18 | get => innerClass.Property1; 19 | set => innerClass.Property1 = value; 20 | } 21 | } 22 | 23 | class InnerClass 24 | { 25 | public string Property1 { get; set; } 26 | } 27 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderLowerCaseBackingFields.cs: -------------------------------------------------------------------------------- 1 | public class MappingFinderLowerCaseBackingFields 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 7 | Assert.Equal("property1", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1").FieldDefinition.Name); 8 | Assert.Equal("property2", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property2").FieldDefinition.Name); 9 | } 10 | 11 | public class ClassWithLowerCaseBackingFields 12 | { 13 | // ReSharper disable ConvertToAutoProperty 14 | string property1; 15 | public string Property1 16 | { 17 | get => property1; 18 | set => property1 = value; 19 | } 20 | 21 | string property2; 22 | public string Property2 23 | { 24 | get => property2; 25 | set => property2 = value; 26 | } 27 | // ReSharper restore ConvertToAutoProperty 28 | } 29 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderSingleBackingConstantFieldGet.cs: -------------------------------------------------------------------------------- 1 | 2 | // ReSharper disable ValueParameterNotUsed 3 | 4 | 5 | public class MappingFinderSingleBackingConstantFieldGet 6 | { 7 | [Fact] 8 | public void Run() 9 | { 10 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 11 | var memberMapping = memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1"); 12 | Assert.Null(memberMapping.FieldDefinition); 13 | } 14 | 15 | public class ClassWithSingleBackingFieldsGet 16 | { 17 | // ReSharper disable ConvertToAutoProperty 18 | const string propertyA = "foo"; 19 | public string Property1 20 | { 21 | get => propertyA; 22 | set { } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderSingleBackingFieldsGet.cs: -------------------------------------------------------------------------------- 1 | 2 | // ReSharper disable ValueParameterNotUsed 3 | #pragma warning disable 649 4 | 5 | 6 | public class MappingFinderSingleBackingFieldsGet 7 | { 8 | [Fact] 9 | public void Run() 10 | { 11 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 12 | Assert.Equal("propertyA", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1").FieldDefinition.Name); 13 | Assert.Equal("propertyB", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property2").FieldDefinition.Name); 14 | } 15 | 16 | public class ClassWithSingleBackingFieldsGet 17 | { 18 | // ReSharper disable ConvertToAutoProperty 19 | string propertyA; 20 | public string Property1 21 | { 22 | get => propertyA; 23 | set { } 24 | } 25 | 26 | string propertyB; 27 | public string Property2 28 | { 29 | get => propertyB; 30 | set { } 31 | } 32 | // ReSharper restore ConvertToAutoProperty 33 | } 34 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderSingleBackingFieldsSet.cs: -------------------------------------------------------------------------------- 1 | public class MappingFinderSingleBackingFieldsSet 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 7 | Assert.Equal("propertyA", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1").FieldDefinition.Name); 8 | Assert.Equal("propertyB", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property2").FieldDefinition.Name); 9 | } 10 | 11 | public class ClassWithSingleBackingFieldsSet 12 | { 13 | // ReSharper disable ConvertToAutoProperty 14 | // ReSharper disable NotAccessedField.Local 15 | string propertyA; 16 | public string Property1 17 | { 18 | get => null; 19 | set => propertyA = value; 20 | } 21 | 22 | string propertyB; 23 | public string Property2 24 | { 25 | get => null; 26 | set => propertyB = value; 27 | } 28 | // ReSharper restore NotAccessedField.Local 29 | // ReSharper restore ConvertToAutoProperty 30 | } 31 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderSingleBackingReadonlyFieldGet.cs: -------------------------------------------------------------------------------- 1 | 2 | // ReSharper disable ConvertToAutoProperty 3 | // ReSharper disable ValueParameterNotUsed 4 | 5 | 6 | public class MappingFinderSingleBackingReadonlyFieldGet 7 | { 8 | [Fact] 9 | public void Run() 10 | { 11 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 12 | var memberMapping = memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1"); 13 | Assert.Null(memberMapping.FieldDefinition); 14 | } 15 | 16 | public class ClassWithSingleBackingFieldsGet 17 | { 18 | readonly string propertyA = "foo"; 19 | public string Property1 20 | { 21 | get => propertyA; 22 | set { } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderUnderScoreBackingFields.cs: -------------------------------------------------------------------------------- 1 | public class MappingFinderUnderScoreBackingFields 2 | { 3 | [Fact] 4 | public void WithLowerUnderScoreBackingFields() 5 | { 6 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 7 | Assert.Equal("_property1", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1").FieldDefinition.Name); 8 | Assert.Equal("_property2", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property2").FieldDefinition.Name); 9 | } 10 | 11 | public class ClassWithUnderScoreBackingFields 12 | { 13 | // ReSharper disable ConvertToAutoProperty 14 | // ReSharper disable InconsistentNaming 15 | string _property1; 16 | public string Property1 17 | { 18 | get => _property1; 19 | set => _property1 = value; 20 | } 21 | 22 | string _property2; 23 | public string Property2 24 | { 25 | get => _property2; 26 | set => _property2 = value; 27 | } 28 | // ReSharper restore InconsistentNaming 29 | // ReSharper restore ConvertToAutoProperty 30 | } 31 | } -------------------------------------------------------------------------------- /Tests/MappingFinder/MappingFinderWithAutoProperties.cs: -------------------------------------------------------------------------------- 1 | public class MappingFinderWithAutoProperties 2 | { 3 | [Fact] 4 | public void Run() 5 | { 6 | 7 | var memberMappings = ModuleWeaver.GetMappings(DefinitionFinder.FindType()).ToList(); 8 | Assert.Equal("k__BackingField", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property1").FieldDefinition.Name); 9 | Assert.Equal("k__BackingField", memberMappings.Single(_ => _.PropertyDefinition.Name == "Property2").FieldDefinition.Name); 10 | } 11 | 12 | public class ClassWithAutoProperties 13 | { 14 | public string Property1 { get; set; } 15 | public string Property2 { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Tests/OnPropertyNameChangedConfigTests.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | 3 | public class OnPropertyNameChangedConfigTests 4 | { 5 | [Fact] 6 | public void False() 7 | { 8 | var xElement = XElement.Parse(""); 9 | var weaver = new ModuleWeaver {Config = xElement}; 10 | weaver.ResolveOnPropertyNameChangedConfig(); 11 | Assert.False(weaver.InjectOnPropertyNameChanged); 12 | } 13 | 14 | [Fact] 15 | public void True() 16 | { 17 | var xElement = XElement.Parse(""); 18 | var weaver = new ModuleWeaver {Config = xElement}; 19 | weaver.ResolveOnPropertyNameChangedConfig(); 20 | Assert.True(weaver.InjectOnPropertyNameChanged); 21 | } 22 | 23 | [Fact] 24 | public void Default() 25 | { 26 | var weaver = new ModuleWeaver(); 27 | weaver.ResolveOnPropertyNameChangedConfig(); 28 | Assert.True(weaver.InjectOnPropertyNameChanged); 29 | } 30 | } -------------------------------------------------------------------------------- /Tests/PropertyInfoCheckers/IndexerCheckerTest.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable ValueParameterNotUsed 3 | 4 | public class IndexerCheckerTest 5 | { 6 | [Fact] 7 | public void IsIndexer() 8 | { 9 | var weaver = new ModuleWeaver(); 10 | var propertyDefinition = DefinitionFinder.FindType() 11 | .Properties 12 | .First(); 13 | 14 | var propertyData = new PropertyData 15 | { 16 | PropertyDefinition = propertyDefinition, 17 | }; 18 | var message = weaver.CheckForWarning(propertyData, InvokerTypes.String); 19 | Assert.Equal("Property is an indexer.", message); 20 | } 21 | 22 | public abstract class IndexerClass 23 | { 24 | public string this[string i] 25 | { 26 | get => null; 27 | set 28 | { 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Tests/RecursiveIlFinderTests.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | public class RecursiveIlFinderTests 4 | { 5 | [Fact] 6 | public void Run() 7 | { 8 | var typeDefinition = DefinitionFinder.FindType(); 9 | var recursiveIlFinder = new RecursiveIlFinder(typeDefinition); 10 | 11 | var methodDefinition = typeDefinition.Methods.First(_ => _.Name == "Method1"); 12 | recursiveIlFinder.Execute(methodDefinition); 13 | #if(DEBUG) 14 | Assert.Equal(25, recursiveIlFinder.Instructions.Count); 15 | #else 16 | Assert.Equal(15, recursiveIlFinder.Instructions.Count); 17 | #endif 18 | } 19 | 20 | public abstract class InnerClass 21 | { 22 | public abstract string AbstractMethod(); 23 | 24 | public void Method1() 25 | { 26 | Property = "aString"; 27 | Method2(); 28 | } 29 | 30 | void Method2() 31 | { 32 | AbstractMethod(); 33 | Method3(); 34 | Method1(); 35 | } 36 | 37 | // ReSharper disable once MemberCanBeMadeStatic.Local 38 | void Method3() 39 | { 40 | Debug.WriteLine("a"); 41 | } 42 | 43 | public string Property { get; set; } 44 | } 45 | } -------------------------------------------------------------------------------- /Tests/TriggerDependentPropertiesConfigTests.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | 3 | public class TriggerDependentPropertiesConfigTests 4 | { 5 | [Fact] 6 | public void False() 7 | { 8 | var xElement = XElement.Parse(""); 9 | var weaver = new ModuleWeaver 10 | { 11 | Config = xElement 12 | }; 13 | weaver.ResolveTriggerDependentPropertiesConfig(); 14 | Assert.False(weaver.TriggerDependentProperties); 15 | } 16 | 17 | [Fact] 18 | public void True() 19 | { 20 | var xElement = XElement.Parse(""); 21 | var weaver = new ModuleWeaver 22 | { 23 | Config = xElement 24 | }; 25 | weaver.ResolveTriggerDependentPropertiesConfig(); 26 | Assert.True(weaver.TriggerDependentProperties); 27 | } 28 | 29 | [Fact] 30 | public void Default() 31 | { 32 | var weaver = new ModuleWeaver(); 33 | weaver.ResolveOnPropertyNameChangedConfig(); 34 | Assert.True(weaver.TriggerDependentProperties); 35 | } 36 | } -------------------------------------------------------------------------------- /Tests/TypeEqualityFinderTests.cs: -------------------------------------------------------------------------------- 1 | using System.Data.SqlTypes; 2 | 3 | public class TypeEqualityFinderTests 4 | { 5 | [Fact] 6 | public void TestSqlGuid() 7 | { 8 | var typeDefinition = DefinitionFinder.FindType(); 9 | var findNamedMethod = ModuleWeaver.FindNamedMethod(typeDefinition); 10 | Assert.Null(findNamedMethod); 11 | } 12 | 13 | [Fact] 14 | public void TestInt() 15 | { 16 | var typeDefinition = DefinitionFinder.FindType(); 17 | var findNamedMethod = ModuleWeaver.FindNamedMethod(typeDefinition); 18 | Assert.Null(findNamedMethod); 19 | } 20 | 21 | [Fact] 22 | public void TestString() 23 | { 24 | var typeDefinition = DefinitionFinder.FindType(); 25 | var findNamedMethod = ModuleWeaver.FindNamedMethod(typeDefinition); 26 | Assert.Equal("System.Boolean System.String::Equals(System.String,System.String)", findNamedMethod.FullName); 27 | } 28 | } -------------------------------------------------------------------------------- /Tests/TypeFilterTests.cs: -------------------------------------------------------------------------------- 1 | public class TypeFilterTests 2 | { 3 | TestResult testResult; 4 | 5 | public TypeFilterTests() 6 | { 7 | var weaver = new ModuleWeaver(); 8 | testResult = weaver.ExecuteTestRun( 9 | "AssemblyWithTypeFilter.dll", 10 | ignoreCodes: ["0x80131869"]); 11 | } 12 | 13 | [Fact] 14 | public void CheckIfFilterTypeExcludeCorrectTypes() 15 | { 16 | var instance = testResult.GetInstance("TestClassExclude"); 17 | EventTester.TestPropertyNotCalled(instance); 18 | } 19 | 20 | [Fact] 21 | public void CheckIfFilterTypeIncludeCorrectTypes() 22 | { 23 | var instance = testResult.GetInstance("PropertyChangedTest.TestClassInclude"); 24 | EventTester.TestProperty(instance, false); 25 | } 26 | 27 | [Fact] 28 | public void CheckIfMultipleFilterTypeIncludeCorrectTypes() 29 | { 30 | var instance1 = testResult.GetInstance("PropertyChangedTest.TestClassInclude"); 31 | var instance2 = testResult.GetInstance("PropertyChangedTestWithDifferentNamespace.TestClassIncludeAlso"); 32 | 33 | EventTester.TestProperty(instance1, false); 34 | EventTester.TestProperty(instance2, false); 35 | } 36 | } -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2022 2 | environment: 3 | DOTNET_NOLOGO: true 4 | DOTNET_CLI_TELEMETRY_OPTOUT: true 5 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 6 | skip_commits: 7 | message: /doco|Merge pull request.*/ 8 | build_script: 9 | - pwsh: | 10 | Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1" 11 | ./dotnet-install.ps1 -JSonFile global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet' 12 | - dotnet build --configuration Release 13 | - dotnet test --configuration Release --no-build --no-restore 14 | test: off 15 | artifacts: 16 | - path: nugets\**\*.nupkg -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.200", 4 | "allowPrerelease": true, 5 | "rollForward": "latestFeature" 6 | } 7 | } -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2012 Simon Cropp and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 20 | 21 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /package_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fody/PropertyChanged/a7de98072c1d4e1737cc1b304277ed14c7da09bb/package_icon.png --------------------------------------------------------------------------------