diff --git a/Events.csproj b/Events.csproj
new file mode 100644
index 0000000..ecb789f
--- /dev/null
+++ b/Events.csproj
@@ -0,0 +1,57 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {E1D98F4B-A176-4F33-BFAE-BE21ECF6DABB}
+ Exe
+ Properties
+ Events
+ Events
+ v4.6
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Events.sln b/Events.sln
new file mode 100644
index 0000000..f2c09d0
--- /dev/null
+++ b/Events.sln
@@ -0,0 +1,16 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Events", "Events.csproj", "{E1D98F4B-A176-4F33-BFAE-BE21ECF6DABB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E1D98F4B-A176-4F33-BFAE-BE21ECF6DABB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E1D98F4B-A176-4F33-BFAE-BE21ECF6DABB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E1D98F4B-A176-4F33-BFAE-BE21ECF6DABB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E1D98F4B-A176-4F33-BFAE-BE21ECF6DABB}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Events.sln.DotSettings b/Events.sln.DotSettings
new file mode 100644
index 0000000..2cb67b2
--- /dev/null
+++ b/Events.sln.DotSettings
@@ -0,0 +1,346 @@
+
+ ExplicitlyExcluded
+ 1432A03F-24C2-4B04-976B-3F4ED1099D40
+ AADE1DF5-4C46-4760-B72B-474D90336F5B
+ CA31A6F2-E679-40C8-8F2C-3ED17AB1455E
+ ECBEC3F9-402C-49C2-A29A-2DEEFE52548F
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ DO_NOT_SHOW
+ DO_NOT_SHOW
+ <?xml version="1.0" encoding="utf-16"?><Profile name="Cleanup"><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><HtmlReformatCode>True</HtmlReformatCode><JsInsertSemicolon>True</JsInsertSemicolon><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs><OptimizeReferenceCommentsTs>True</OptimizeReferenceCommentsTs><PublicModifierStyleTs>True</PublicModifierStyleTs><ExplicitAnyTs>True</ExplicitAnyTs><TypeAnnotationStyleTs>True</TypeAnnotationStyleTs><RelativePathStyleTs>True</RelativePathStyleTs><AsInsteadOfCastTs>True</AsInsteadOfCastTs><XMLReformatCode>True</XMLReformatCode><CppAddOverrideSpecifier>True</CppAddOverrideSpecifier><CppAddTypenameTemplateKeywords>True</CppAddTypenameTemplateKeywords><CppReplaceImportDirective>True</CppReplaceImportDirective><CppRemoveElseKeyword>True</CppRemoveElseKeyword><CppShortenQualifiedName>True</CppShortenQualifiedName><CppDeleteRedundantSpecifier>True</CppDeleteRedundantSpecifier><CppRemoveStatement>True</CppRemoveStatement><CppDeleteRedundantTypenameTemplateKeywords>True</CppDeleteRedundantTypenameTemplateKeywords><CppReplaceExpressionWithBooleanConst>True</CppReplaceExpressionWithBooleanConst><CppMakePostfixOperatorPrefix>True</CppMakePostfixOperatorPrefix><CppChangeSmartPointerToMakeFunction>True</CppChangeSmartPointerToMakeFunction><CppReplaceThrowWithRethrowFix>True</CppReplaceThrowWithRethrowFix><CppReplaceExpressionWithNullptr>True</CppReplaceExpressionWithNullptr><CppSortMemberInitializers>True</CppSortMemberInitializers><CppReformatCode>True</CppReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="True" ArrangeCodeBodyStyle="True" ArrangeVarStyle="False" /><RemoveCodeRedundanciesVB>True</RemoveCodeRedundanciesVB><CssAlphabetizeProperties>True</CssAlphabetizeProperties><VBOptimizeImports>True</VBOptimizeImports><VBShortenReferences>True</VBShortenReferences><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CssReformatCode>True</CssReformatCode><VBReformatCode>True</VBReformatCode><VBFormatDocComments>True</VBFormatDocComments><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSReorderTypeMembers>True</CSReorderTypeMembers><IDEA_SETTINGS><profile version="1.0">
+ <option name="myName" value="Cleanup" />
+</profile></IDEA_SETTINGS></Profile>
+ Cleanup
+ False
+ UseClrName
+ UseClrName
+ TOGETHER_SAME_LINE
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ NEVER
+ True
+ False
+ Tab
+ 300
+ True
+ Tab
+ False
+ <?xml version="1.0" encoding="utf-16"?>
+<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
+ <TypePattern DisplayName="Non-reorderable types">
+ <TypePattern.Match>
+ <Or>
+ <And>
+ <Kind Is="Interface" />
+ <Or>
+ <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" />
+ <HasAttribute Name="System.Runtime.InteropServices.ComImport" />
+ </Or>
+ </And>
+ <Kind Is="Struct" />
+ <HasAttribute Name="JetBrains.Annotations.NoReorderAttribute" />
+ <HasAttribute Name="JetBrains.Annotations.NoReorder" />
+ </Or>
+ </TypePattern.Match>
+ </TypePattern>
+ <TypePattern DisplayName="xUnit.net Test Classes" RemoveRegions="All">
+ <TypePattern.Match>
+ <And>
+ <Kind Is="Class" />
+ <HasMember>
+ <And>
+ <Kind Is="Method" />
+ <HasAttribute Name="Xunit.FactAttribute" Inherited="True" />
+ </And>
+ </HasMember>
+ </And>
+ </TypePattern.Match>
+ <Entry DisplayName="Setup/Teardown Methods">
+ <Entry.Match>
+ <Or>
+ <Kind Is="Constructor" />
+ <And>
+ <Kind Is="Method" />
+ <ImplementsInterface Name="System.IDisposable" />
+ </And>
+ </Or>
+ </Entry.Match>
+ <Entry.SortBy>
+ <Kind Order="Constructor" />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="All other members" />
+ <Entry DisplayName="Test Methods" Priority="100">
+ <Entry.Match>
+ <And>
+ <Kind Is="Method" />
+ <HasAttribute Name="Xunit.FactAttribute" />
+ </And>
+ </Entry.Match>
+ <Entry.SortBy>
+ <Name />
+ </Entry.SortBy>
+ </Entry>
+ </TypePattern>
+ <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All">
+ <TypePattern.Match>
+ <And>
+ <Kind Is="Class" />
+ <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" />
+ </And>
+ </TypePattern.Match>
+ <Entry DisplayName="Setup/Teardown Methods">
+ <Entry.Match>
+ <And>
+ <Kind Is="Method" />
+ <Or>
+ <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" />
+ <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" />
+ <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" />
+ <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" />
+ </Or>
+ </And>
+ </Entry.Match>
+ </Entry>
+ <Entry DisplayName="All other members" />
+ <Entry DisplayName="Test Methods" Priority="100">
+ <Entry.Match>
+ <And>
+ <Kind Is="Method" />
+ <HasAttribute Name="NUnit.Framework.TestAttribute" />
+ </And>
+ </Entry.Match>
+ <Entry.SortBy>
+ <Name />
+ </Entry.SortBy>
+ </Entry>
+ </TypePattern>
+ <TypePattern DisplayName="Type layout" RemoveRegions="AllExceptGenerated">
+ <TypePattern.Match>
+ <Or>
+ <Kind Is="Class" />
+ <Kind Is="Struct" />
+ <Kind Is="Interface" />
+ </Or>
+ </TypePattern.Match>
+ <Entry DisplayName="Extern">
+ <Entry.Match>
+ <Extern />
+ </Entry.Match>
+ </Entry>
+ <Entry DisplayName="Constants">
+ <Entry.Match>
+ <Kind Is="Constant" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Fields">
+ <Entry.Match>
+ <Kind Is="Field" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Static />
+ <Access />
+ <Readonly />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Constructors">
+ <Entry.Match>
+ <Kind Is="Constructor" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Static />
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Finalizers">
+ <Entry.Match>
+ <Kind Is="Destructor" />
+ </Entry.Match>
+ </Entry>
+ <Entry DisplayName="Delegates">
+ <Entry.Match>
+ <Kind Is="Delegate" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Events">
+ <Entry.Match>
+ <Kind Is="Event" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Static />
+ <Access />
+ <Abstract />
+ <ImplementsInterface />
+ <Virtual />
+ <Override />
+ <Sealed />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Enums">
+ <Entry.Match>
+ <Kind Is="Enum" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Interfaces">
+ <Entry.Match>
+ <Kind Is="Interface" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Properties">
+ <Entry.Match>
+ <Kind Is="Property" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Static />
+ <Access />
+ <Abstract />
+ <ImplementsInterface />
+ <Virtual />
+ <Override />
+ <Sealed />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Operators">
+ <Entry.Match>
+ <Kind Is="Operator" />
+ </Entry.Match>
+ </Entry>
+ <Entry DisplayName="Indexers">
+ <Entry.Match>
+ <Kind Is="Indexer" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ <Abstract />
+ <ImplementsInterface />
+ <Virtual />
+ <Override />
+ <Sealed />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Methods">
+ <Entry.Match>
+ <Kind Is="Method" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Static />
+ <Access />
+ <Abstract />
+ <ImplementsInterface />
+ <Virtual />
+ <Override />
+ <Sealed />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Structs">
+ <Entry.Match>
+ <Kind Is="Struct" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Classes">
+ <Entry.Match>
+ <Kind Is="Class" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ </TypePattern>
+ <FilePattern>
+ <Entry DisplayName="Extern alias directives">
+ <Entry.Match>
+ <Extern />
+ </Entry.Match>
+ </Entry>
+ <Entry DisplayName="Delegates">
+ <Entry.Match>
+ <Kind Is="Delegate" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Enums">
+ <Entry.Match>
+ <Kind Is="Enum" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Interfaces">
+ <Entry.Match>
+ <Kind Is="Interface" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Structs">
+ <Entry.Match>
+ <Kind Is="Struct" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ <Entry DisplayName="Classes">
+ <Entry.Match>
+ <Kind Is="Class" />
+ </Entry.Match>
+ <Entry.SortBy>
+ <Access />
+ </Entry.SortBy>
+ </Entry>
+ </FilePattern>
+</Patterns>
+ UseExplicitType
+ UseVarWhenEvident
+ UseVarWhenEvident
+ False
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ No
+ True
+ PackageReference
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/Product.cs b/Product.cs
index f68c8c9..3145062 100644
--- a/Product.cs
+++ b/Product.cs
@@ -2,74 +2,73 @@
namespace Events
{
- ///
- /// Класс должен описывать представление о товаре.
- /// В рамках лабораторной работы должен являться
- /// источником события
- ///
- class Product
- {
+ ///
+ /// Класс должен описывать представление о товаре.
+ /// В рамках лабораторной работы должен являться
+ /// источником события
+ ///
+ internal class Product
+ {
+ ///
+ /// Наименование
+ ///
+ private String _name;
- #region Variables
- ///
- /// Наименование
- ///
- private string name;
- ///
- /// Стоимость
- ///
- private decimal price;
+ ///
+ /// Стоимость
+ ///
+ private Decimal _price;
- #endregion
+ public Product(String name, Decimal price)
+ {
+ Name = name;
+ Price = price;
+ }
- #region Properties
+ ///
+ /// Возникает, когда имя продукта было изменено.
+ ///
+ public event EventHandler NameChanged;
- ///
- /// Наименование
- ///
- public string Name
- {
- get { return name; }
- set
- {
- name = value;
- /*
- * TODO #4 Инициировать уведомление об
- * изменении наименования
- */
- }
- }
- ///
- /// Стоимость
- ///
- public decimal Price
- {
- get { return price; }
- set
- {
- price = value;
- /*
- * TODO #5 Инициировать уведомление об
- * изменении стоимости
- */
- }
- }
+ ///
+ /// Возникает, когда цена продукта была изменена.
+ ///
+ public event EventHandler PriceChanged;
- #endregion
+ ///
+ /// Наименование
+ ///
+ public String Name
+ {
+ get => _name;
+ set
+ {
+ if (_name == value)
+ return;
- #region Events
+ String oldName = _name;
- /*
- * TODO #3 Добавить определение событий
- */
+ _name = value;
+ NameChanged?.Invoke(this, new ProductEventArgs(oldName, _name, _price, _price));
+ }
+ }
- #endregion
+ ///
+ /// Стоимость
+ ///
+ public Decimal Price
+ {
+ get => _price;
+ set
+ {
+ if (_price == value)
+ return;
- public Product(string name, decimal price)
- {
- Name = name;
- Price = price;
- }
+ Decimal oldPrice = _price;
- }
-}
+ _price = value;
+ PriceChanged?.Invoke(this, new ProductEventArgs(_name, _name, oldPrice, _price));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ProductEventArgs.cs b/ProductEventArgs.cs
index a79a6d6..a74926c 100644
--- a/ProductEventArgs.cs
+++ b/ProductEventArgs.cs
@@ -1,18 +1,43 @@
-namespace Events
+using System;
+
+namespace Events
{
- ///
- /// Класс, который служит для передачи аргументов
- /// в обработчик событий, возникающих в классе
- /// Product
- ///
- /*
- * TODO #1 Закончить определение класса ProductEventArgs
- */
- class ProductEventArgs
- {
- /*
- * TODO #2 Добавить определение необходимых компонент
- * класса ProductEventArgs
- */
- }
-}
+ ///
+ /// Класс, который служит для передачи аргументов
+ /// в обработчик событий, возникающих в классе
+ /// Product
+ ///
+ internal class ProductEventArgs : EventArgs
+ {
+ public readonly String OldName;
+ public readonly String NewName;
+ public readonly Decimal OldPrice;
+ public readonly Decimal NewPrice;
+
+ public ProductEventArgs(String oldName, String newName, Decimal oldPrice, Decimal newPrice)
+ {
+ OldName = oldName;
+ NewName = newName;
+ OldPrice = oldPrice;
+ NewPrice = newPrice;
+ }
+
+ ///
+ /// Определяет, изменилось ли имя продукта.
+ ///
+ public Boolean IsNameChanged => OldName != NewName;
+
+ ///
+ /// Определяет, изменилась ли цена продукта.
+ ///
+ public Boolean IsPriceChanged => OldPrice != NewPrice;
+
+ public override String ToString()
+ {
+ String nameDiff = IsNameChanged ? $"{OldName} -> {NewName}" : "unchanged";
+ String priceDiff = IsPriceChanged ? $"{OldPrice} -> {NewPrice}" : "unchanged";
+
+ return $"Name: {nameDiff}, Price: {priceDiff}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
index b9247f7..e67d9de 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,37 +1,31 @@
-namespace Events
+using System;
+
+namespace Events
{
- class Program
- {
- internal Product Product
- {
- get
- {
- throw new System.NotImplementedException();
- }
+ internal static class Program
+ {
+ private static void Main(String[] args)
+ {
+ Product product = new Product("Some product name", 0);
- set
- {
- throw new System.NotImplementedException();
- }
- }
+ product.NameChanged += ProductOnNameChanged;
+ product.PriceChanged += ProductOnPriceChanged;
- static void Main(string[] args)
- {
- Product product = new Product("Some product name", 0);
-
- /*
- * TODO #6 Назначить обработчики событий в текущем контексте
- */
+ Console.WriteLine("Changing name");
+ product.Name = "Iron plates";
- /*
- * TODO #7 Выполнить с экземпляром класса Product действия,
- * приводящие к возникновению описанных Вами событий
- */
- }
+ Console.WriteLine("Changing price");
+ product.Price = 42;
+ }
- /*
- * TODO #8 Добавить определение обработчиков событий
- */
+ private static void ProductOnPriceChanged(Object sender, ProductEventArgs e)
+ {
+ Console.WriteLine(e);
+ }
- }
-}
+ private static void ProductOnNameChanged(Object sender, ProductEventArgs e)
+ {
+ Console.WriteLine(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a71e40f
--- /dev/null
+++ b/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Events")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Events")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("E1D98F4B-A176-4F33-BFAE-BE21ECF6DABB")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file