{"id":2204,"date":"2024-10-31T10:00:23","date_gmt":"2024-10-31T10:00:23","guid":{"rendered":"https:\/\/www.w3computing.com\/articles\/?p=2204"},"modified":"2024-10-31T10:00:27","modified_gmt":"2024-10-31T10:00:27","slug":"how-to-handle-circular-dependencies-in-csharp-projects","status":"publish","type":"post","link":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/","title":{"rendered":"How to Handle Circular Dependencies in C# Projects"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes, interfaces, and modules can quickly lead to dependency issues. In this guide, I\u2019ll walk you through how to effectively manage, identify, and resolve circular dependencies in C# projects. We\u2019ll cover various techniques and best practices to address circular dependencies, giving practical, step-by-step examples along the way.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding Circular Dependencies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before diving into solutions, let&#8217;s start by defining what a circular dependency is and why it can be problematic in C#. A circular dependency occurs when two or more modules, classes, or assemblies depend on each other directly or indirectly, forming a cycle in the dependency graph. For example:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Direct circular dependency<\/strong>: Class <code>A<\/code> depends on class <code>B<\/code>, and class <code>B<\/code> depends on class <code>A<\/code>.<\/li>\n\n\n\n<li><strong>Indirect circular dependency<\/strong>: Class <code>A<\/code> depends on class <code>B<\/code>, class <code>B<\/code> depends on class <code>C<\/code>, and class <code>C<\/code> depends on class <code>A<\/code>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Circular dependencies are generally considered bad design, as they lead to tightly coupled code, making it harder to manage, test, and understand. Furthermore, circular dependencies can lead to issues at runtime, especially when trying to initialize dependent components, causing potential stack overflow exceptions and other unpredictable behaviors.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Circular Dependencies Happen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Circular dependencies can arise due to several common coding practices:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Bi-directional communication<\/strong> between classes, where each class relies on the other.<\/li>\n\n\n\n<li><strong>Inheritance hierarchies<\/strong> where a base class depends on derived classes.<\/li>\n\n\n\n<li><strong>Helper classes or utilities<\/strong> inadvertently referencing the classes they\u2019re helping.<\/li>\n\n\n\n<li><strong>Poor architectural separation<\/strong> of concerns, leading to entangled dependencies.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">With these root causes in mind, let&#8217;s look at methods for detecting and handling circular dependencies.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Detecting Circular Dependencies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In many C# IDEs, particularly Visual Studio, circular dependencies may not trigger errors until runtime or when you start analyzing the project. Some steps to detect them include:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.1 Using Visual Studio&#8217;s Dependency Validation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In Visual Studio, you can visualize and validate dependencies with <strong>Dependency Diagrams<\/strong>. This feature allows you to see the relationships between your assemblies, namespaces, and classes, and it can help detect cycles. To create a dependency diagram:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Right-click on your project and select <strong>Add > New Item<\/strong>.<\/li>\n\n\n\n<li>Choose <strong>Dependency Diagram<\/strong>.<\/li>\n\n\n\n<li>Drag and drop your projects, namespaces, and classes to visualize their dependencies.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Visual Studio will alert you to circular dependencies, allowing you to spot issues early.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.2 Static Code Analysis Tools<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Static analysis tools like <strong>NDepend<\/strong> and <strong>ReSharper<\/strong> are also valuable. These tools analyze your codebase and can detect dependency cycles, giving detailed reports that allow you to pinpoint problematic relationships between classes or assemblies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.3 Manual Code Review<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">While not as efficient for large projects, manually reviewing code can help in smaller projects or specific cases. Look for classes with <code>using<\/code> directives that reference each other or constructors that instantiate objects of other classes in a loop.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Refactoring to Break Circular Dependencies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once you&#8217;ve identified a circular dependency, the next step is to refactor your code to remove it. Below are several techniques to achieve this.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.1 Use Interfaces to Decouple Dependencies<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A common technique for breaking circular dependencies is to use interfaces. By introducing an interface, you can change direct dependencies between classes into abstractions, making it easier to avoid cycles.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose we have a circular dependency between <code>OrderService<\/code> and <code>CustomerService<\/code>. <code>OrderService<\/code> needs to know about customers, and <code>CustomerService<\/code> needs to know about orders.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Step-by-Step Solution:<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Define an Interface<\/strong>: Create an <code>ICustomerService<\/code> interface that <code>CustomerService<\/code> implements.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">ICustomerService<\/span>\n   {\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">AddCustomer<\/span>(<span class=\"hljs-params\">Customer customer<\/span>)<\/span>;\n       <span class=\"hljs-function\">Customer <span class=\"hljs-title\">GetCustomer<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">int<\/span> id<\/span>)<\/span>;\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Refactor the Dependent Class<\/strong>: Modify <code>OrderService<\/code> to depend on <code>ICustomerService<\/code> rather than <code>CustomerService<\/code>.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">OrderService<\/span>\n   {\n       <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> ICustomerService _customerService;\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">OrderService<\/span>(<span class=\"hljs-params\">ICustomerService customerService<\/span>)<\/span>\n       {\n           _customerService = customerService;\n       }\n\n       <span class=\"hljs-comment\">\/\/ Other methods<\/span>\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Inject Dependencies via Constructor<\/strong>: Use dependency injection (DI) to inject <code>ICustomerService<\/code> into <code>OrderService<\/code>, ideally by configuring it in the startup or DI container.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   services.AddScoped&lt;ICustomerService, CustomerService&gt;();\n   services.AddScoped&lt;OrderService&gt;();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">By using this approach, <code>OrderService<\/code> no longer directly depends on <code>CustomerService<\/code>, thus breaking the cycle.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.2 Apply Dependency Inversion Principle (DIP)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>Dependency Inversion Principle<\/strong> states that high-level modules should not depend on low-level modules. Both should depend on abstractions. This principle is beneficial in cases where two classes need each other\u2019s functionality.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consider two classes, <code>ClassA<\/code> and <code>ClassB<\/code>, where both require methods from each other.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Step-by-Step Solution:<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Define interfaces for each class\u2019s required behavior.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">IClassA<\/span>\n   {\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">DoSomething<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>;\n   }\n\n   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">IClassB<\/span>\n   {\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">DoSomethingElse<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>;\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>Implement each class with the appropriate interfaces.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ClassA<\/span> : <span class=\"hljs-title\">IClassA<\/span>\n   {\n       <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> IClassB _classB;\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ClassA<\/span>(<span class=\"hljs-params\">IClassB classB<\/span>)<\/span>\n       {\n           _classB = classB;\n       }\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">DoSomething<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>\n       {\n           <span class=\"hljs-comment\">\/\/ Logic here<\/span>\n           _classB.DoSomethingElse();\n       }\n   }\n\n   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ClassB<\/span> : <span class=\"hljs-title\">IClassB<\/span>\n   {\n       <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> IClassA _classA;\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ClassB<\/span>(<span class=\"hljs-params\">IClassA classA<\/span>)<\/span>\n       {\n           _classA = classA;\n       }\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">DoSomethingElse<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>\n       {\n           <span class=\"hljs-comment\">\/\/ Logic here<\/span>\n           _classA.DoSomething();\n       }\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>Configure dependency injection in a way that resolves these interfaces without creating a direct circular dependency.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">By applying DIP, you can decouple these classes and avoid cycles by ensuring they rely on abstractions instead of each other directly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2.3 Introduce a Mediator or Service Locator<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In cases where multiple classes need to communicate bidirectionally, a <strong>Mediator<\/strong> or <strong>Service Locator<\/strong> pattern can help separate the dependencies, reducing the likelihood of a cycle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Mediator Pattern Example<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine <code>UserManager<\/code> and <code>NotificationService<\/code> need to notify each other about certain events.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Step-by-Step Solution:<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a <code>IMediator<\/code> interface with methods that allow both <code>UserManager<\/code> and <code>NotificationService<\/code> to communicate indirectly.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">IMediator<\/span>\n   {\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">Notify<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">object<\/span> sender, <span class=\"hljs-keyword\">string<\/span> ev<\/span>)<\/span>;\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>Implement the <code>Mediator<\/code> to handle these events.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ConcreteMediator<\/span> : <span class=\"hljs-title\">IMediator<\/span>\n   {\n       <span class=\"hljs-keyword\">private<\/span> UserManager _userManager;\n       <span class=\"hljs-keyword\">private<\/span> NotificationService _notificationService;\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ConcreteMediator<\/span>(<span class=\"hljs-params\">UserManager userManager, NotificationService notificationService<\/span>)<\/span>\n       {\n           _userManager = userManager;\n           _notificationService = notificationService;\n       }\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">Notify<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">object<\/span> sender, <span class=\"hljs-keyword\">string<\/span> ev<\/span>)<\/span>\n       {\n           <span class=\"hljs-keyword\">if<\/span> (ev == <span class=\"hljs-string\">\"UserCreated\"<\/span>)\n           {\n               _notificationService.SendNotification();\n           }\n           <span class=\"hljs-keyword\">else<\/span> <span class=\"hljs-keyword\">if<\/span> (ev == <span class=\"hljs-string\">\"NotificationSent\"<\/span>)\n           {\n               _userManager.HandleNotification();\n           }\n       }\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>Modify <code>UserManager<\/code> and <code>NotificationService<\/code> to use <code>IMediator<\/code> instead of each other directly, breaking the dependency cycle.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Using a mediator simplifies the interdependencies and centralizes the communication, making it easier to manage.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Design Patterns to Minimize Circular Dependencies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Applying certain design patterns can minimize the risk of circular dependencies, especially in projects with complex relationships.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.1 Observer Pattern<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>Observer Pattern<\/strong> is ideal when you need to notify multiple classes about state changes in another class, without creating a tight coupling between them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Assume <code>WeatherStation<\/code> notifies multiple display devices (<code>WeatherDisplay<\/code>, <code>StatisticsDisplay<\/code>) about temperature updates.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Step-by-Step Solution:<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create an <code>IObserver<\/code> interface for the displays to implement.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">IObserver<\/span>\n   {\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">Update<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">float<\/span> temperature<\/span>)<\/span>;\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>Implement the <code>IObserver<\/code> in display classes.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WeatherDisplay<\/span> : <span class=\"hljs-title\">IObserver<\/span>\n   {\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">Update<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">float<\/span> temperature<\/span>)<\/span>\n       {\n           Console.WriteLine(<span class=\"hljs-string\">$\"WeatherDisplay: <span class=\"hljs-subst\">{temperature}<\/span>\"<\/span>);\n       }\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>Implement the <code>WeatherStation<\/code> class to maintain a list of observers and notify them of changes.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WeatherStation<\/span>\n   {\n       <span class=\"hljs-keyword\">private<\/span> List&lt;IObserver&gt; _observers = <span class=\"hljs-keyword\">new<\/span> List&lt;IObserver&gt;();\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">RegisterObserver<\/span>(<span class=\"hljs-params\">IObserver observer<\/span>)<\/span>\n       {\n           _observers.Add(observer);\n       }\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">NotifyObservers<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">float<\/span> temperature<\/span>)<\/span>\n       {\n           <span class=\"hljs-keyword\">foreach<\/span> (<span class=\"hljs-keyword\">var<\/span> observer <span class=\"hljs-keyword\">in<\/span> _observers)\n           {\n               observer.Update(temperature);\n           }\n       }\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">With the Observer pattern, each display class only depends on the <code>IObserver<\/code> interface, and the <code>WeatherStation<\/code> does not depend directly on any specific display class, breaking any potential cycles.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3.2 Event-Driven Architecture<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An <strong>event-driven approach<\/strong> can eliminate circular dependencies by relying on events instead of direct method calls. When a class raises an event, other classes can subscribe<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">to it and respond independently, reducing direct dependencies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Example<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose <code>InventoryService<\/code> and <code>OrderService<\/code> need to notify each other when orders are placed and inventory changes.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Step-by-Step Solution:<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Define events in <code>OrderService<\/code>.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">OrderService<\/span>\n   {\n       <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">event<\/span> EventHandler OrderPlaced;\n\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">PlaceOrder<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>\n       {\n           <span class=\"hljs-comment\">\/\/ Place order logic<\/span>\n           OrderPlaced?.Invoke(<span class=\"hljs-keyword\">this<\/span>, EventArgs.Empty);\n       }\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>In <code>InventoryService<\/code>, subscribe to the event without directly referencing <code>OrderService<\/code>.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">InventoryService<\/span>\n   {\n       <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">OnOrderPlaced<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">object<\/span> sender, EventArgs e<\/span>)<\/span>\n       {\n           <span class=\"hljs-comment\">\/\/ Update inventory<\/span>\n       }\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>Wire up the event in your main program or DI configuration.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">   <span class=\"hljs-keyword\">var<\/span> orderService = <span class=\"hljs-keyword\">new<\/span> OrderService();\n   <span class=\"hljs-keyword\">var<\/span> inventoryService = <span class=\"hljs-keyword\">new<\/span> InventoryService();\n\n   orderService.OrderPlaced += inventoryService.OnOrderPlaced;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Events allow <code>OrderService<\/code> to signal changes without being tightly coupled to <code>InventoryService<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Structuring Projects to Avoid Circular Dependencies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Proper project structure can prevent circular dependencies at a higher level. Some strategies include:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Layered Architecture<\/strong>: Separate the project into layers (e.g., Presentation, Business Logic, Data Access), each only depending on the layer below.<\/li>\n\n\n\n<li><strong>Domain-Driven Design (DDD)<\/strong>: Isolate domain logic into well-defined bounded contexts, avoiding tight coupling across contexts.<\/li>\n\n\n\n<li><strong>Modularization<\/strong>: Divide your project into independent modules, each with a clear responsibility and limited dependencies.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">By following these architectural guidelines, you can minimize circular dependencies and create a more maintainable project structure.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Wrapping Up<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Handling circular dependencies in C# requires a good understanding of design principles, dependency management, and best practices. Through dependency inversion, patterns like Mediator and Observer, and strategic project structuring, you can effectively avoid circular dependencies and keep your project modular and maintainable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Managing dependencies is crucial to software quality, so apply these techniques thoughtfully and refactor as necessary. As you gain experience, recognizing and avoiding circular dependencies will become more intuitive, resulting in cleaner, more robust C# code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes, interfaces, and modules can quickly lead to dependency issues. In this guide, I\u2019ll walk you through how to effectively manage, identify, and resolve circular dependencies in C# projects. We\u2019ll cover various techniques and best practices [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[8,4],"tags":[],"class_list":["post-2204","post","type-post","status-publish","format-standard","category-csharp","category-programming-languages","entry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to Handle Circular Dependencies in C# Projects<\/title>\n<meta name=\"description\" content=\"Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Handle Circular Dependencies in C# Projects\" \/>\n<meta property=\"og:description\" content=\"Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-10-31T10:00:23+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-31T10:00:27+00:00\" \/>\n<meta name=\"author\" content=\"w3compadmin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"w3compadmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/\"},\"author\":{\"name\":\"w3compadmin\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"headline\":\"How to Handle Circular Dependencies in C# Projects\",\"datePublished\":\"2024-10-31T10:00:23+00:00\",\"dateModified\":\"2024-10-31T10:00:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/\"},\"wordCount\":1176,\"articleSection\":[\"C#\",\"Programming Languages\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/\",\"name\":\"How to Handle Circular Dependencies in C# Projects\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\"},\"datePublished\":\"2024-10-31T10:00:23+00:00\",\"dateModified\":\"2024-10-31T10:00:27+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"description\":\"Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/how-to-handle-circular-dependencies-in-csharp-projects\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Articles Home\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Programming Languages\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/programming-languages\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"C#\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/programming-languages\\\/csharp\\\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"How to Handle Circular Dependencies in C# Projects\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\",\"name\":\"Developer Articles Hub\",\"description\":\"\",\"alternateName\":\"Developer Articles\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\",\"name\":\"w3compadmin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781352167\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781352167\",\"contentUrl\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781352167\",\"caption\":\"w3compadmin\"},\"sameAs\":[\"http:\\\/\\\/w3computing.com\\\/articles\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Handle Circular Dependencies in C# Projects","description":"Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/","og_locale":"en_US","og_type":"article","og_title":"How to Handle Circular Dependencies in C# Projects","og_description":"Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes","og_url":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/","article_published_time":"2024-10-31T10:00:23+00:00","article_modified_time":"2024-10-31T10:00:27+00:00","author":"w3compadmin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"w3compadmin","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/#article","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/"},"author":{"name":"w3compadmin","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"headline":"How to Handle Circular Dependencies in C# Projects","datePublished":"2024-10-31T10:00:23+00:00","dateModified":"2024-10-31T10:00:27+00:00","mainEntityOfPage":{"@id":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/"},"wordCount":1176,"articleSection":["C#","Programming Languages"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/","url":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/","name":"How to Handle Circular Dependencies in C# Projects","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/#website"},"datePublished":"2024-10-31T10:00:23+00:00","dateModified":"2024-10-31T10:00:27+00:00","author":{"@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"description":"Handling circular dependencies in C# projects can be a challenging task, especially in large or complex projects where interconnected classes","breadcrumb":{"@id":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.w3computing.com\/articles\/how-to-handle-circular-dependencies-in-csharp-projects\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Articles Home","item":"https:\/\/www.w3computing.com\/articles\/"},{"@type":"ListItem","position":2,"name":"Programming Languages","item":"https:\/\/www.w3computing.com\/articles\/programming-languages\/"},{"@type":"ListItem","position":3,"name":"C#","item":"https:\/\/www.w3computing.com\/articles\/programming-languages\/csharp\/"},{"@type":"ListItem","position":4,"name":"How to Handle Circular Dependencies in C# Projects"}]},{"@type":"WebSite","@id":"https:\/\/www.w3computing.com\/articles\/#website","url":"https:\/\/www.w3computing.com\/articles\/","name":"Developer Articles Hub","description":"","alternateName":"Developer Articles","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.w3computing.com\/articles\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561","name":"w3compadmin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781352167","url":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781352167","contentUrl":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1781352167","caption":"w3compadmin"},"sameAs":["http:\/\/w3computing.com\/articles"]}]}},"featured_image_src":null,"featured_image_src_square":null,"author_info":{"display_name":"w3compadmin","author_link":"https:\/\/www.w3computing.com\/articles\/author\/w3compadmin\/"},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/2204","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/comments?post=2204"}],"version-history":[{"count":2,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/2204\/revisions"}],"predecessor-version":[{"id":2206,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/2204\/revisions\/2206"}],"wp:attachment":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/media?parent=2204"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/categories?post=2204"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/tags?post=2204"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}