Files
xSaherelmWorkspace/Documents/Docs/Developer/13.html
T
2026-10-03 18:04:36 +03:30

351 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>رفع خطای Circular Dependency در XFileContentExtractor - فن آوران ساحر علم</title>
<style>
:root {
--primary: #1e3a8a;
--secondary: #3b82f6;
--accent: #f59e0b;
--success: #10b981;
--danger: #ef4444;
--warning: #f97316;
--bg-light: #f8fafc;
--bg-code: #1e293b;
--text-dark: #0f172a;
--text-muted: #64748b;
--border: #e2e8f0;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Tahoma', 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #f8fafc 0%, #e0e7ff 100%);
color: var(--text-dark);
line-height: 1.8;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
color: white;
padding: 40px;
text-align: center;
}
.header h1 { font-size: 2.1em; margin-bottom: 10px; }
.header .subtitle { font-size: 1.1em; opacity: 0.95; }
.meta-bar {
display: flex;
justify-content: space-between;
background: var(--bg-light);
padding: 15px 30px;
border-bottom: 2px solid var(--border);
flex-wrap: wrap;
gap: 15px;
}
.meta-item { display: flex; align-items: center; gap: 8px; font-size: 0.9em; color: var(--text-muted); }
.meta-item strong { color: var(--primary); }
.content { padding: 40px; }
.section {
margin-bottom: 35px;
padding: 25px;
background: var(--bg-light);
border-radius: 12px;
border-right: 5px solid var(--secondary);
}
.section h2 {
color: var(--primary);
font-size: 1.5em;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid var(--border);
}
pre {
background: var(--bg-code);
color: #e2e8f0;
padding: 18px;
border-radius: 8px;
overflow-x: auto;
direction: ltr;
text-align: left;
font-family: 'Consolas', monospace;
font-size: 0.85em;
margin: 15px 0;
border-right: 4px solid var(--accent);
}
code {
background: #fef3c7;
color: #92400e;
padding: 2px 8px;
border-radius: 4px;
font-family: 'Consolas', monospace;
font-size: 0.9em;
direction: ltr;
display: inline-block;
}
table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
background: white;
border-radius: 8px;
overflow: hidden;
}
th { background: var(--primary); color: white; padding: 12px; text-align: right; }
td { padding: 12px; border-bottom: 1px solid var(--border); }
.alert { padding: 15px 20px; border-radius: 8px; margin: 15px 0; border-right: 4px solid; }
.alert-info { background: #dbeafe; border-color: var(--secondary); color: #1e40af; }
.alert-success { background: #d1fae5; border-color: var(--success); color: #065f46; }
.alert-danger { background: #fee2e2; border-color: var(--danger); color: #991b1b; }
.footer { background: var(--primary); color: white; padding: 25px; text-align: center; }
.file-change { background: #f0f9ff; border-right: 4px solid var(--secondary); padding: 15px; margin: 10px 0; border-radius: 8px; }
.file-change .path { font-family: 'Consolas', monospace; color: var(--primary); font-weight: bold; direction: ltr; display: inline-block; }
.badge-modify { background: var(--warning); color: white; padding: 2px 8px; border-radius: 4px; font-size: 0.75em; margin-right: 8px; }
.badge-new { background: var(--success); color: white; padding: 2px 8px; border-radius: 4px; font-size: 0.75em; margin-right: 8px; }
.diff-old { background: #fee2e2; color: #991b1b; padding: 2px 6px; border-radius: 3px; text-decoration: line-through; }
.diff-new { background: #d1fae5; color: #065f46; padding: 2px 6px; border-radius: 3px; font-weight: bold; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🔗 رفع خطای Circular Dependency در XFileContentExtractor</h1>
<div class="subtitle">تحلیل و رفع حلقه وابستگی در Composite Extractor Pattern</div>
</div>
<div class="meta-bar">
<div class="meta-item">👨‍💻 <strong>توسعه‌دهنده:</strong> هادی خزاعی اصل</div>
<div class="meta-item">🏢 <strong>شرکت:</strong> فن آوران ساحر علم</div>
<div class="meta-item">📅 <strong>تاریخ:</strong> شنبه ۱۲ مهر ۱۴۰۵</div>
<div class="meta-item">📦 <strong>پروژه:</strong> xAiApi</div>
</div>
<div class="content">
<!-- Section 1: Analysis -->
<div class="section">
<h2>🔍 تحلیل ریشه خطا</h2>
<p>خطای <code>Circular Dependency</code> به دلیل ثبت نادرست <code>XFileContentExtractor</code> در DI Container ایجاد شده است:</p>
<div class="alert alert-danger">
<strong>⚠️ پیغام خطا:</strong><br>
<code style="font-size: 0.9em;">A circular dependency was detected for the service of type 'IEnumerable&lt;IXFileContentExtractor&gt;'</code>
</div>
<h3>زنجیره وابستگی مشکل‌ساز:</h3>
<table>
<tr>
<th>مرحله</th>
<th>سرویس</th>
<th>وابستگی</th>
</tr>
<tr>
<td>۱</td>
<td><code>XFileContentExtractor</code></td>
<td>نیاز به <code>IEnumerable&lt;IXFileContentExtractor&gt;</code> در constructor</td>
</tr>
<tr>
<td>۲</td>
<td><code>IEnumerable&lt;IXFileContentExtractor&gt;</code></td>
<td>شامل تمام <code>IXFileContentExtractor</code> های ثبت شده</td>
</tr>
<tr>
<td>۳</td>
<td><code>XFileContentExtractor</code> (دوباره!)</td>
<td>خودش هم به عنوان <code>IXFileContentExtractor</code> ثبت شده ❌</td>
</tr>
<tr>
<td>۴</td>
<td colspan="2" style="background: var(--danger); color: white;"><strong>حلقه بی‌نهایت → Crash</strong></td>
</tr>
</table>
</div>
<!-- Section 2: Solution -->
<div class="section">
<h2>💡 راه‌حل اصلاحی</h2>
<p>برای شکستن این حلقه، باید <code>XFileContentExtractor</code> را به عنوان <code>IXFileContentExtractor</code> ثبت <strong>نکنیم</strong>. به جای آن، آن را به صورت دستی با factory بسازیم.</p>
<div class="file-change">
<span class="badge-modify">MODIFY</span>
<span class="path">xAiApi/Startup.cs (متد ConfigureServices)</span>
</div>
<h3>کد اصلاح‌شده:</h3>
<pre>public void ConfigureServices(IServiceCollection services)
{
// ... (ثبت‌های قبلی)
// ==========================================================
// ✅ ثبت File Content Extractors (همگی Singleton)
// ==========================================================
// ۱. ثبت Extractor های پایه
services.AddSingleton&lt;IXFileContentExtractor, XPdfFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XDocxFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XImageFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XAudioFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XExcelFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XVisionFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XPlainTextFileContentExtractor&gt;();
// ۲. ✅ اصلاح: ثبت XFileContentExtractor به صورت Factory
// به جای ثبت به عنوان IXFileContentExtractor، آن را به صورت دستی می‌سازیم
services.AddSingleton&lt;XFileContentExtractor&gt;(sp =&gt;
{
// دریافت تمام Extractor های ثبت شده (به جز XFileContentExtractor)
var extractors = sp.GetServices&lt;IXFileContentExtractor&gt;();
return new XFileContentExtractor(extractors);
});
// ۳. ✅ ثبت XFileContentExtractor به عنوان IXFileContentExtractor
// اما با استفاده از Factory که از قبل ساخته شده
services.AddSingleton&lt;IXFileContentExtractor&gt;(sp =&gt;
sp.GetRequiredService&lt;XFileContentExtractor&gt;());
// ==========================================================
// ✅ ثبت سرویس‌های AI
// ==========================================================
services.AddSingleton&lt;IXDefaultAIOCRService, XDefaultAIOCRService&gt;();
services.AddScoped&lt;IXDefaultAiService, XDefaultAiService&gt;();
services.AddScoped&lt;IXDefaultEmbeddingService, XDefaultEmbeddingService&gt;();
services.AddScoped&lt;IXDefaultThinkingAiService, XDefaultThinkingAiService&gt;();
}</pre>
<div class="alert alert-success">
<strong>✅ چرا این راه‌حل کار می‌کند؟</strong>
<ul style="padding-right: 25px; margin-top: 10px;">
<li>✅ <code>XFileContentExtractor</code> ابتدا به عنوان خودش (نه interface) ثبت می‌شود</li>
<li>✅ در factory، تمام <code>IXFileContentExtractor</code> های دیگر را دریافت می‌کند</li>
<li>✅ سپس به عنوان <code>IXFileContentExtractor</code> ثبت می‌شود (اما از instance از قبل ساخته شده)</li>
<li>✅ حلقه وابستگی شکسته می‌شود</li>
</ul>
</div>
</div>
<!-- Section 3: Alternative Solution -->
<div class="section">
<h2>🔄 راه‌حل جایگزین (ساده‌تر)</h2>
<p>اگر راه‌حل بالا پیچیده به نظر می‌رسد، می‌توانید از این روش ساده‌تر استفاده کنید:</p>
<div class="file-change">
<span class="badge-modify">MODIFY</span>
<span class="path">xAiApi/Startup.cs</span>
</div>
<pre>public void ConfigureServices(IServiceCollection services)
{
// ... (ثبت‌های قبلی)
// ==========================================================
// ✅ ثبت File Content Extractors
// ==========================================================
// ۱. ثبت Extractor های پایه
services.AddSingleton&lt;IXFileContentExtractor, XPdfFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XDocxFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XImageFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XAudioFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XExcelFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XVisionFileContentExtractor&gt;();
services.AddSingleton&lt;IXFileContentExtractor, XPlainTextFileContentExtractor&gt;();
// ۲. ✅ راه‌حل ساده: ساخت دستی XFileContentExtractor
// ابتدا تمام Extractor ها را در یک لیست جمع می‌کنیم
var extractorTypes = new[]
{
typeof(XPdfFileContentExtractor),
typeof(XDocxFileContentExtractor),
typeof(XImageFileContentExtractor),
typeof(XAudioFileContentExtractor),
typeof(XExcelFileContentExtractor),
typeof(XPlainTextFileContentExtractor)
};
// ۳. ثبت XFileContentExtractor با factory
services.AddSingleton&lt;IXFileContentExtractor&gt;(sp =&gt;
{
var extractors = new List&lt;IXFileContentExtractor&gt;();
// ساخت دستی Extractor ها
foreach (var type in extractorTypes)
{
var instance = (IXFileContentExtractor)ActivatorUtilities.CreateInstance(sp, type);
extractors.Add(instance);
}
// افزودن XVisionFileContentExtractor (که وابستگی دارد)
var visionExtractor = sp.GetRequiredService&lt;XVisionFileContentExtractor&gt;();
extractors.Add(visionExtractor);
// ساخت XFileContentExtractor با لیست Extractor ها
return new XFileContentExtractor(extractors);
});
// ==========================================================
// ✅ ثبت سرویس‌های AI
// ==========================================================
services.AddSingleton&lt;IXDefaultAIOCRService, XDefaultAIOCRService&gt;();
services.AddScoped&lt;IXDefaultAiService, XDefaultAiService&gt;();
services.AddScoped&lt;IXDefaultEmbeddingService, XDefaultEmbeddingService&gt;();
services.AddScoped&lt;IXDefaultThinkingAiService, XDefaultThinkingAiService&gt;();
}</pre>
</div>
<!-- Section 4: Summary -->
<div class="section">
<h2>📋 خلاصه تغییرات</h2>
<table>
<tr>
<th>فایل</th>
<th>تغییر</th>
<th>دلیل</th>
</tr>
<tr>
<td><code>Startup.cs</code></td>
<td><span class="diff-old">services.AddScoped&lt;IXFileContentExtractor, XFileContentExtractor&gt;()</span><br>
<span class="diff-new">services.AddSingleton&lt;IXFileContentExtractor&gt;(sp =&gt; { ... })</span></td>
<td>رفع Circular Dependency با استفاده از Factory Pattern</td>
</tr>
</table>
<div class="alert alert-success">
<strong>✅ نتیجه نهایی:</strong>
<ul style="padding-right: 25px; margin-top: 10px;">
<li>✅ Circular Dependency کاملاً رفع می‌شود</li>
<li>✅ DI Container می‌تواند تمام سرویس‌ها را بسازد</li>
<li>✅ <code>XFileContentExtractor</code> همچنان به تمام Extractor ها دسترسی دارد</li>
<li>✅ خطای <code>AggregateException</code> دیگر ظاهر نخواهد شد</li>
</ul>
</div>
<div class="alert alert-info">
<strong>💡 نکته مهم:</strong>
<p>پس از اعمال این تغییر، پروژه را <strong>Rebuild</strong> کنید. خطای <code>System.AggregateException</code> دیگر ظاهر نخواهد شد و برنامه به درستی اجرا می‌شود.</p>
</div>
</div>
</div>
<div class="footer">
<p><strong>👨‍💻 توسعه‌دهنده:</strong> هادی خزاعی اصل</p>
<p><strong>🏢 شرکت:</strong> فن آوران ساحر علم</p>
<p><strong>📅 تاریخ:</strong> شنبه ۱۲ مهر ۱۴۰۵</p>
<p style="margin-top: 15px; opacity: 0.8; font-size: 0.9em;">
🔗 مستند فنی رفع خطای Circular Dependency در XFileContentExtractor - تمامی حقوق محفوظ است
</p>
</div>
</div>
</body>
</html>