<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: .NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: .NET</description><language>ar</language><item><title>&#x62E;&#x62F;&#x645;&#x627;&#x62A; &#x627;&#x633;&#x62A;&#x62F;&#x639;&#x627;&#x621; &#x627;&#x644;&#x645;&#x646;&#x635;&#x629; Platform Invoke &#x641;&#x64A; dot Net</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%AE%D8%AF%D9%85%D8%A7%D8%AA-%D8%A7%D8%B3%D8%AA%D8%AF%D8%B9%D8%A7%D8%A1-%D8%A7%D9%84%D9%85%D9%86%D8%B5%D8%A9-platform-invoke-%D9%81%D9%8A-dot-net-r1004/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/26.png.69971d1b83398c5e10a290b8f59e886a.png" /></p>

<h2>
	خدمات استدعاء المنصة Platform Invocation Services
</h2>

<p>
	يُشار إلى الشيفرة التي تُنفَّذ داخل بيئة التَّنفيذ المشتركة (CLR) باسم الشيفرة المُدارة (managed code) بخلاف الشيفرة التي تُنفَّذ خارجها، والتي يُشار إليها بطبيعة الحال باسم الشيفرة غير المُدارة (unmanaged code).
</p>

<p>
	تَتوفَّر العديد من الطرائق لتَسهِيل العمليات بين الشيفرات (interoperability) من كِلَا النوعين. تُعدّ خدمات اِستدعاء المنصة <code>Platform Invocation Services</code> إحداها.
</p>

<h3>
	استدعاء شيفرة غير مُدارة من أُخرى مُدارة
</h3>

<p>
	يُمكِنك استدعاء إحدى الدوال غير المُدارة مثل دوال واجهة ويندوز لبرمجة التطبيقات <code>Windows <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></code> -في حالة عدم وجودها بمكتبات الأصناف المُدارة (class libraries)- عن طريق التََّصرِيح عن تابع خارجي ساكن (static extern) يَحمِل نفس بَصمة الدالة المطلوب استدعائها. سيُعدّ هذا التابع بمثابة مُمثِل للدالة غير المُدارة بحيث تستطيع استدعائها باستدعائه. لتحقيق ذلك، لابُدّ أن يُزَخرَف هذا التابع بالسمة <code>DllImportAttribute</code> مع تمرير اسم مكتبة dll التي توجد بها تلك الدالة كمُعامِل للسمة.
</p>

<p>
	عند استدعائك لهذا التابع، ستُحمِّل خدمات استدعاء المنصة <code>Platform Invocation Services</code> مكتبة dll المُخصَّصة، ثم تَستدعِي الدالة غير المُدارة المُناظِرة للتابع.
</p>

<p>
	ستَحتاج إلى تَضمِين فضاء الاسم <code>System.Runtime.InteropServices</code>.
</p>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_7" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Runtime</span><span class="pun">.</span><span class="typ">InteropServices</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PInvokeExample</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">DllImport</span><span class="pun">(</span><span class="str">"user32.dll"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CharSet</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CharSet</span><span class="pun">.</span><span class="typ">Auto</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">extern</span><span class="pln"> </span><span class="typ">uint</span><span class="pln"> </span><span class="typ">MessageBox</span><span class="pun">(</span><span class="typ">IntPtr</span><span class="pln"> hWnd</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> text</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> caption</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> options</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> test</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">MessageBox</span><span class="pun">(</span><span class="typ">IntPtr</span><span class="pun">.</span><span class="typ">Zero</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Hello!"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Message"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	اِستعِن بتوثيق <a href="http://pinvoke.net/" rel="external nofollow">pinvoke.net</a> قبل التَّصرِيح عن تابع خارجي مُمثِل لإحدى دوال واجهة ويندوز لبرمجة التطبيقات <code>Windows <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></code>، فغالبًا ستَجِدْ معلومات عن الطريقة المُلائمة للتَّصرِيح عنه مع جميع الأنواع المطلوبة كمُعامِلات أو كنوع للقيمة المُعادة بالإضافة إلى بعض الأمثلة التوضيحية.
</p>

<h2>
	ترتيب الأنواع (Marshalling)
</h2>

<p>
	في حالة وجود مُعامِلات للدوال غير المُدارة أو قيم مُعادَة منها، فغالبًا ما تَتَمَكَّن خدمات استدعاء المنصة <code>Platform Invocation Services</code> من تحويل أنواع ‎.NET المُدارة -بالتحديد الأنواع البسيطة- إلى أنواع المكتبة المُستخدَمة ضِمْن الاستدعاء والعكس تحويلًا أتوماتيكيًا وبدون تعليمات إضافية. تُعرَف هذه العملية باسم الترتيب (Marshalling).
</p>

<p>
	أما إذا كان المُعامِل من نوع مُركَّب مثل <code>struct</code> أو <code>union</code>، فستَحتَاج إلى التَّصرِيح عن صنف جديد <code>struct</code> أو <code>class</code> بشيفرة الـ c#‎ الخاصة بك. يَعمَل هذا الصنف كمُمثِل للنوع غير المُدار، ولابُدّ أن يُزخرَف بالسمة <code>StructLayoutAttribute</code> لإعلام المُرَتِّب (marshaler) بطريقة رَبْط الحُقول (mapping). قد تحتاج أيضًا إلى مزيد من التَخصِيص.
</p>

<h3>
	ترتيب النوع <code>union</code>
</h3>

<p>
	يَستعرِض المثال التالي تَّصرِيح مكتبة c++‎ عن صنف <code>union</code> مُكَّون من حقول من نوع القيمة فقط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_9" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">union</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="typ">CharOrInt</span></pre>

<p>
	في هذه الحالة، تستطيع اِستخدَام <code>LayoutKind.Explicit</code> كقيمة لمُعامِل السمة <code>StructLayout</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_11" style="">
<span class="pun">[</span><span class="typ">StructLayout</span><span class="pun">(</span><span class="typ">LayoutKind</span><span class="pun">.</span><span class="typ">Explicit</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">CharOrInt</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">FieldOffset</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> byte c</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">FieldOffset</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أما إذا كان الصنف <code>union</code> مُكَّون من حقول من نَوعي القيمة والمَرجِع، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_13" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">union</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> text</span><span class="pun">[</span><span class="lit">128</span><span class="pun">];</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="typ">TextOrInt</span><span class="pun">;</span></pre>

<p>
	في هذه الحالة، لا يُمكِنك مجرد اِستخدَام السمة <code>FieldOffset</code> كالمثال الأسبق. وإنما ستحتاج في الغالب إلى تَخصِيص عملية الترتيب (marshaling).
</p>

<p>
	مع ذلك، يُعدّ المثال بالأعلى بسيطًا نوعا ما، وتَتوفَّر طريقة مُبسَّطة باِستخدَام القيمة <code>LayoutKind.Sequential</code> كقيمة لمُعامِل السمة <code>StructLayout</code> مما يعني طريقة تسلسُليّة لرَبْط الحقول (mapping).
</p>

<p>
	قد تحتاج بعض أنواع حقول الصنف إلى الزَخرَفة باستخدَام السمة <code>MarshalAs</code> لتَخصِيص النوع غير المُدار المُناظِر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_15" style="">
<span class="pun">[</span><span class="typ">StructLayout</span><span class="pun">(</span><span class="typ">LayoutKind</span><span class="pun">.</span><span class="typ">Sequential</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">TextOrInt</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">MarshalAs</span><span class="pun">(</span><span class="typ">UnmanagedType</span><span class="pun">.</span><span class="typ">ByValArray</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SizeConst</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">128</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> text</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">{</span><span class="pln"> get </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToInt32</span><span class="pun">(</span><span class="pln">text</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	ترتيب النوع <code>struct</code>
</h3>

<p>
	يستعرض المثال التالي تَّصرِيح مكتبة c++‎ عن صنف <code>struct</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_17" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> _PERSON
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> age</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> name</span><span class="pun">[</span><span class="lit">32</span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> PERSON</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln">LP_PERSON</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">GetSpouse</span><span class="pun">(</span><span class="pln">PERSON person</span><span class="pun">,</span><span class="pln"> LP_PERSON spouse</span><span class="pun">);</span></pre>

<p>
	بصورة مشابهة للأنواع <code>unions</code>. ستحتاج إلى تَعرِيف نوع جديد مُزخرَف باستخدام السمة <code>StructLayout</code> يُمثِل نَظيره غير المُدار، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_19" style="">
<span class="pun">[</span><span class="typ">StructLayout</span><span class="pun">(</span><span class="typ">LayoutKind</span><span class="pun">.</span><span class="typ">Sequential</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CharSet</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CharSet</span><span class="pun">.</span><span class="typ">Ansi</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> PERSON
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> age</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">MarshalAs</span><span class="pun">(</span><span class="typ">UnmanagedType</span><span class="pun">.</span><span class="typ">ByValTStr</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SizeConst</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">32</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">[</span><span class="typ">DllImport</span><span class="pun">(</span><span class="str">"family.dll"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CharSet</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CharSet</span><span class="pun">.</span><span class="typ">Auto</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">extern</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">GetSpouse</span><span class="pun">(</span><span class="pln">PERSON person</span><span class="pun">,</span><span class="pln"> ref PERSON spouse</span><span class="pun">);</span></pre>

<h3>
	ترتيب حقل مصفوفة غير مَعْلومة الحجم (إرسال)
</h3>

<p>
	بصمة c++‎:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_21" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> length</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">data</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> VECTOR</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SetVector</span><span class="pun">(</span><span class="pln">VECTOR </span><span class="pun">&amp;</span><span class="typ">vector</span><span class="pun">);</span></pre>

<p>
	في هذه الحالة، ينبغي أن يُمرَّر حقل المصفوفة غير مَعْلومة الحجم كقيمة من النوع <code>IntPtr</code> مع الاستدعاء الصريح للتابعين <a href="https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.allochglobal(v=vs.110).aspx" rel="external nofollow">Marshal.AllocHGlobal()</a>‎ و <a href="https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.freehglobal(v=vs.110).aspx" rel="external nofollow">Marshal.FreeHGlobal()</a>‎ من أجل تَخصِيص مساحة بالذاكرة لهذا الحقل وتَّفرِيغها على الترتيب، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_23" style="">
<span class="pun">[</span><span class="typ">StructLayout</span><span class="pun">(</span><span class="typ">LayoutKind</span><span class="pun">.</span><span class="typ">Sequential</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> VECTOR </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IDisposable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> length</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">IntPtr</span><span class="pln"> dataBuf</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[]</span><span class="pln"> data
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">set</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">FreeDataBuf</span><span class="pun">();</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">value </span><span class="pun">!=</span><span class="pln"> null </span><span class="pun">&amp;&amp;</span><span class="pln"> value</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                dataBuf </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Marshal</span><span class="pun">.</span><span class="typ">AllocHGlobal</span><span class="pun">(</span><span class="pln">value</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="typ">Marshal</span><span class="pun">.</span><span class="typ">SizeOf</span><span class="pun">(</span><span class="pln">value</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]));</span><span class="pln">
                </span><span class="typ">Marshal</span><span class="pun">.</span><span class="typ">Copy</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> dataBuf</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span><span class="pln">
                length </span><span class="pun">=</span><span class="pln"> value</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">FreeDataBuf</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">dataBuf </span><span class="pun">!=</span><span class="pln"> </span><span class="typ">IntPtr</span><span class="pun">.</span><span class="typ">Zero</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Marshal</span><span class="pun">.</span><span class="typ">FreeHGlobal</span><span class="pun">(</span><span class="pln">dataBuf</span><span class="pun">);</span><span class="pln">
            dataBuf </span><span class="pun">=</span><span class="pln"> </span><span class="typ">IntPtr</span><span class="pun">.</span><span class="typ">Zero</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Dispose</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">FreeDataBuf</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">[</span><span class="typ">DllImport</span><span class="pun">(</span><span class="str">"vectors.dll"</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">extern</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SetVector</span><span class="pun">([</span><span class="typ">In</span><span class="pun">]</span><span class="pln">ref VECTOR </span><span class="typ">vector</span><span class="pun">);</span></pre>

<h3>
	ترتيب حقل مصفوفة غير مَعْلومة الحجم (استقبال)
</h3>

<p>
	بصمة C++‎:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_25" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> USER</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">GetCurrentUser</span><span class="pun">(</span><span class="pln">USER </span><span class="pun">*</span><span class="pln">user</span><span class="pun">);</span></pre>

<p>
	عند استقبال شيفرة مُدارة لمصفوفة غير مَعْلومة الحجم من أُخرى غير مُدارة، فإن مساحة الذاكرة التي تَشغَلها المصفوفة تكون بطبيعة الحال مُخصَّصة بواسطة دوال الشيفرة غير المُدارة.
</p>

<p>
	في هذه الحالة، ينبغي للشيفرة المُدارة أن تَستقبِل البيانات إلى مُتغير من النوع <code>IntPrt</code> ثم تَقرَّأ بيانات المُخزِّن المؤقت (buffer) إلى مصفوفة مُدارة.
</p>

<p>
	إذا كانت المصفوفة من النوع <code>string</code>، يُمكن استخدام التابع <a href="https://msdn.microsoft.com/en-us/library/7b620dhe(v=vs.110).aspx" rel="external nofollow">Marshal.PtrToStringAnsi()</a>‎ المُخَصَّص لهذا الغرض.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_27" style="">
<span class="pun">[</span><span class="typ">StructLayout</span><span class="pun">(</span><span class="typ">LayoutKind</span><span class="pun">.</span><span class="typ">Sequential</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> USER
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">IntPtr</span><span class="pln"> nameBuffer</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string name </span><span class="pun">{</span><span class="pln"> 
        get </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Marshal</span><span class="pun">.</span><span class="typ">PtrToStringAnsi</span><span class="pun">(</span><span class="pln">nameBuffer</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> 
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">[</span><span class="typ">DllImport</span><span class="pun">(</span><span class="str">"users.dll"</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">extern</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">GetCurrentUser</span><span class="pun">(</span><span class="pln">out USER user</span><span class="pun">);</span></pre>

<h3>
	ترتيب مصفوفة
</h3>

<p>
	إذا كانت مصفوفة من نوع بسيط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_29" style="">
<span class="pun">[</span><span class="typ">DllImport</span><span class="pun">(</span><span class="str">"Example.dll"</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">extern</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SetArray</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">MarshalAs</span><span class="pun">(</span><span class="typ">UnmanagedType</span><span class="pun">.</span><span class="typ">LPArray</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SizeConst</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">128</span><span class="pun">)]</span><span class="pln">
    byte</span><span class="pun">[]</span><span class="pln"> data</span><span class="pun">);</span></pre>

<p>
	إذا كانت مصفوفة من النوع <code>string</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5709_31" style="">
<span class="pun">[</span><span class="typ">DllImport</span><span class="pun">(</span><span class="str">"Example.dll"</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">extern</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SetStrArray</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> textLines</span><span class="pun">);</span></pre>

<p>
	ترجمة -وبتصرف- للفصل Platform Invoke من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1004</guid><pubDate>Thu, 17 Sep 2020 13:05:29 +0000</pubDate></item><item><title>&#x62A;&#x645;&#x64A;&#x64A;&#x632; &#x627;&#x644;&#x643;&#x644;&#x627;&#x645; &#x62A;&#x644;&#x642;&#x627;&#x626;&#x64A;&#x64B;&#x627; speech recognition &#x641;&#x64A; dot Net</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%AA%D9%85%D9%8A%D9%8A%D8%B2-%D8%A7%D9%84%D9%83%D9%84%D8%A7%D9%85-%D8%AA%D9%84%D9%82%D8%A7%D8%A6%D9%8A%D9%8B%D8%A7-speech-recognition-%D9%81%D9%8A-dot-net-r1003/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/25.png.f69be1f3615771fd02d82781125a358d.png" /></p>

<p>
	يُوفِّر إطار عمل <code>‎.NET</code> الصنف <code>SpeechRecognitionEngine</code> بفضاء الاسم <code>System.Speech.Recognition</code> لتَميِيز الكلام تلقائيًا.
</p>

<p>
	يُدعِّم مُمَيِّز الكلام -من النوع <code>SpeechRecognitionEngine</code>- عِدة أحَدَاث (events) تُثار تلقائيًا عند حُدوث ظرف معين. يُمكِن لمُعالِجات الأحَدَاث (event handlers) التَسجيل بتلك الأحداث، مما يَسمَح بإجراء العمليات المطلوبة بشكل غَيْر مُتزامِن (asynchronous).
</p>

<p>
	يُعدّ الحَدَث <code>SpeechRecognized</code> أحد أهم أحداث النوع <code>SpeechRecognitionEngine</code>، والذي يُثَار عندما يَستقبِل مُمَيِّز الكلام دَخْلًا يَتوَافق مع إحدى قواعده المُفعَّلة. تُخصَّص تلك القواعد من خلال كائن من النوع <code>Grammar</code> يُمرَّر للتابع <code>LoadGrammar</code> لوضع قيود على عملية تَميِيز الكلام.
</p>

<p>
	تَعرِض الشيفرة بالأسفل طريقة اِستخدَام النوع <code>SpeechRecognitionEngine</code> لبناء مُعالِج للحَدَث <code>SpeechRecognized</code> يقوم بإرسال الكلام المُمَيَّز إلى مَجْرى الخَرْج.
</p>

<p>
	تنشئة مُمَيِّز الكلام كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8697_7" style="">
<span class="typ">SpeechRecognitionEngine</span><span class="pln"> recognitionEngine </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SpeechRecognitionEngine</span><span class="pun">();</span></pre>

<p>
	التَسجيل بالحَدث <code>SpeechRecognized</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8697_9" style="">
<span class="pln">recognitionEngine</span><span class="pun">.</span><span class="typ">SpeechRecognized</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="kwd">delegate</span><span class="pun">(</span><span class="pln">object sender</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SpeechRecognizedEventArgs</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"You said: {0}"</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">Result</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	بدء تشغيل المُمَيِّز كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8697_11" style="">
<span class="pln">recognitionEngine</span><span class="pun">.</span><span class="typ">SetInputToDefaultAudioDevice</span><span class="pun">();</span><span class="pln">
recognitionEngine</span><span class="pun">.</span><span class="typ">RecognizeAsync</span><span class="pun">(</span><span class="typ">RecognizeMode</span><span class="pun">.</span><span class="typ">Multiple</span><span class="pun">);</span></pre>

<h2>
	تمييز مقيد بمجموعة جمل باستخدام <code>GrammarBuilder</code>
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8697_13" style="">
<span class="typ">SpeechRecognitionEngine</span><span class="pln"> recognitionEngine </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SpeechRecognitionEngine</span><span class="pun">();</span><span class="pln">

</span><span class="typ">GrammarBuilder</span><span class="pln"> builder </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">GrammarBuilder</span><span class="pun">();</span><span class="pln">
builder</span><span class="pun">.</span><span class="typ">Append</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Choices</span><span class="pun">(</span><span class="str">"I am"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"You are"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"He is"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"She is"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"We are"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"They are"</span><span class="pun">));</span><span class="pln">
builder</span><span class="pun">.</span><span class="typ">Append</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Choices</span><span class="pun">(</span><span class="str">"friendly"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"unfriendly"</span><span class="pun">));</span><span class="pln">

recognitionEngine</span><span class="pun">.</span><span class="typ">LoadGrammar</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Grammar</span><span class="pun">(</span><span class="pln">builder</span><span class="pun">));</span><span class="pln">

recognitionEngine</span><span class="pun">.</span><span class="typ">SpeechRecognized</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="kwd">delegate</span><span class="pun">(</span><span class="pln">object sender</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SpeechRecognizedEventArgs</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"You said: {0}"</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">Result</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

recognitionEngine</span><span class="pun">.</span><span class="typ">SetInputToDefaultAudioDevice</span><span class="pun">();</span><span class="pln">
recognitionEngine</span><span class="pun">.</span><span class="typ">RecognizeAsync</span><span class="pun">(</span><span class="typ">RecognizeMode</span><span class="pun">.</span><span class="typ">Multiple</span><span class="pun">);</span></pre>

<h2>
	تمييز حر بدون قيود (free text) باستخدام <code>DictationGrammar</code>
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8697_15" style="">
<span class="typ">SpeechRecognitionEngine</span><span class="pln"> recognitionEngine </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SpeechRecognitionEngine</span><span class="pun">();</span><span class="pln">

recognitionEngine</span><span class="pun">.</span><span class="typ">LoadGrammar</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DictationGrammar</span><span class="pun">());</span><span class="pln">

recognitionEngine</span><span class="pun">.</span><span class="typ">SpeechRecognized</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="kwd">delegate</span><span class="pun">(</span><span class="pln">object sender</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SpeechRecognizedEventArgs</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"You said: {0}"</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">Result</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

recognitionEngine</span><span class="pun">.</span><span class="typ">SetInputToDefaultAudioDevice</span><span class="pun">();</span><span class="pln">
recognitionEngine</span><span class="pun">.</span><span class="typ">RecognizeAsync</span><span class="pun">(</span><span class="typ">RecognizeMode</span><span class="pun">.</span><span class="typ">Multiple</span><span class="pun">);</span></pre>

<p>
	ملاحظات:
</p>

<ul>
<li>
		مُعامِلات التابع <code>LoadGrammar</code>:

		<ul>
<li>
				grammar: من النوع <code>Grammar</code> يُشير إلى القواعد التي يَنبغي تَحميلها. مثلًا، يُستخدَم كائن من النوع <code>DictationGrammar</code> -المُشتَق من النوع <code>Grammar</code>- لتمييز حُر دون قيود.
			</li>
		</ul>
</li>
	<li>
		مُعامِلات باني النوع <code>Grammar</code>:
		<ul>
<li>
				builder: من النوع <code>GrammarBuilder</code>.
			</li>
		</ul>
</li>
	<li>
		مُعامِلات التابع <code>GrammarBuilder.Append</code>:
		<ul>
<li>
				choices: من النوع <code>Choices</code>. يُلحِق هذا التابع مُكَوِّنًا جديد بتَسَلسُل القواعد (grammar sequence)، مع السَماح بعدة بدائل (choices) ضِمْن ذلك المُكَوِّن. يعني ذلك أنه عند اِستقبَال دَخْل صوتي من المُستخدِم، يُمكِن للمُمَيِّز اتباع عدة بدائل من القواعد.
			</li>
		</ul>
</li>
	<li>
		مُعامِلات باني النوع <code>Choices</code>:
		<ul>
<li>
				choices: مصفوفة من البدائل.
			</li>
		</ul>
</li>
	<li>
		مُعامِلات التابع <code>RecognizeAsync</code>:
		<ul>
<li>
				mode: من النوع تعداد <code>RecognizeMode</code>، لتحديد عدد عمليات التَميِيز المُمكن إجرائها إِمّا <code>Single</code> أو <code>Multiple</code>
			</li>
		</ul>
</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل SpeechRecognitionEngine class to recognize speech من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1003</guid><pubDate>Thu, 08 Oct 2020 18:08:02 +0000</pubDate></item><item><title>&#x646;&#x645;&#x627;&#x630;&#x62C; VB.NET &#x641;&#x64A; dot Net</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D9%86%D9%85%D8%A7%D8%B0%D8%AC-vbnet-%D9%81%D9%8A-dot-net-r1002/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/24.png.9346bc31cddf063cc7c69e1aab4a7b54.png" /></p>

<p>
	تتكون تقنية <code>Forms</code> من عدة مكتبات تُسهِل من عملية تطوير التطبيقات. النموذج أو الاستمارة (form) هو ببساطة واجهة مُستخدِم مُكَوَّنة من عدة عناصر منفصلة (controls). تُستخدَم هذه العناصر لعَرْض معلومات للمُستخدِم أو استقبال مُدخَلات منه.
</p>

<p>
	تَعتمِد برمجة تطبيقات <code>Forms</code> بشكل أساسي على مفهوم الأحَدَاث (events)، والتي تُثار تلقائيًا عند ظرف معين أو نتيجة تَفاعُل المُستخدِم مع البرنامج. بالتالي، لابُد للبرنامج أن يُعالِج هذه الأحداث (event handlers) بتَّنْفيذ الإجراء المُتناسب.
</p>

<h2>
	برنامج "أهلا بالعالم"
</h2>

<p>
	على سبيل المثال، يُثار الحَدَث <code>Load</code> مرة وحيدة عند تَحمِيل النموذج (form) وعَرضه لأول مرة. في المقابل، يُثار الحَدَث <code>Shown</code> في كل مرة يُعرَض فيها النموذج.
</p>

<p>
	لعَرْض مربع رسالة (message box) في كل مرة يُعرَض فيها النموذج، اِستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1472_7" style="">
<span class="typ">Public</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="typ">Form1</span><span class="pln">
    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Form1_Shown</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">MyBase</span><span class="pun">.</span><span class="typ">Shown</span><span class="pln">
        </span><span class="typ">MessageBox</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="str">"Hello, World!"</span><span class="pun">)</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">
</span><span class="typ">End</span><span class="pln"> </span><span class="typ">Class</span></pre>

<p>
	لِعَرْضِها مرة واحدة فقط عند تَحمِيل النموذج، اِستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1472_9" style="">
<span class="typ">Public</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="typ">Form1</span><span class="pln">
    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Form1_Load</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">MyBase</span><span class="pun">.</span><span class="typ">Load</span><span class="pln">
        </span><span class="typ">MessageBox</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="str">"Hello, World!"</span><span class="pun">)</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">
</span><span class="typ">End</span><span class="pln"> </span><span class="typ">Class</span></pre>

<p>
	يُثار أيضًا الحَدَث <code>Activate</code> في كل مرة يقوم فيها المُستخدِم بتَفعيل النموذج.
</p>

<p>
	تنبيه: يُثار الحَدَث <code>Load</code> قبل الحَدَث <code>Show</code>. مع ذلك، إذا اِستدعَى مُعالِج الحَدَث <code>Show</code> التابع <code>msgBox</code> لِعَرْض مربع رسالة، فقد يؤدي ذلك إلى تَّنْفيذ التابع <code>msgBox</code> قبل انتهاء تنفيذ مُعالِج الحََدَث <code>Load</code>. لذلك، عامةً، لا يُنصَح بالاعتماد على ترتيب إثارة الحَدَثين <code>Load</code> و <code>Show</code>.
</p>

<h2>
	المؤقت <code>Timer</code>
</h2>

<p>
	لنفترض أن لدينا نموذج (form) يحتوي على العناصر التالية: زر، وعنوان (label)، ومؤقت (timer). يُهيئ المثال التالي مُعالِج حَدَث الضغط على الزر. يَعرِض ذلك المُعالِج التوقيت الحالي للمُستخدِم ثم يَضبُط مؤقت لمدة دقيقة، بعد انتهائها يُثار الحدث <code>Tick</code> تلقائيًا، مما يؤدي إلى تَّنْفيذ مُعالِج الحدث <code>Tick</code> الذي يُحدِّث قيمة الوقت المعروض:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1472_11" style="">
<span class="typ">Public</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="typ">Form1</span><span class="pln">

    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Button1_Click</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">Button1</span><span class="pun">.</span><span class="typ">Click</span><span class="pln">
        </span><span class="typ">Button1</span><span class="pun">.</span><span class="typ">Enabled</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">False</span><span class="pln">
        </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Interval</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1000</span><span class="pln"> </span><span class="str">'</span><span class="pln">one minute intervals
        </span><span class="str">'</span><span class="pln">start timer
        </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">()</span><span class="pln">
        </span><span class="typ">Label1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">.</span><span class="typ">ToLongTimeString</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">

    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Timer1_Tick</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Tick</span><span class="pln">
        </span><span class="typ">Label1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">.</span><span class="typ">ToLongTimeString</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">

</span><span class="typ">End</span><span class="pln"> </span><span class="typ">Class</span></pre>

<p>
	مثال آخر هو محاولة اِستخدَام عنصر المؤقت <code>Timer</code> لمحاكاة مؤقت للعد التنازلي (countdown) لمدة معينة -مثلًا 3 دقائق.
</p>

<p>
	كالمثال السابق، يُضبَط المؤقت عند الضغط على الزر. لكن، في هذا المثال، ستُستخدََم أيضًا ساعة توقيت من النوع <code>Stopwatch</code> لموازنة مدة المؤقت المُحدَّدة مع الوقت الفعلي المُنصرِم منذ لحظة ضَبْط المؤقت وحتى تنْفيذ مُعالِج الحدث <code>Tick</code>. يَعرِض مُعالِج الحدث <code>Tick</code> الزمن المُنصرم بوحدة الثواني:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1472_13" style="">
<span class="typ">Public</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="typ">Form1</span><span class="pln">

    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Button1_Click</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">Button1</span><span class="pun">.</span><span class="typ">Click</span><span class="pln">
        </span><span class="typ">Button1</span><span class="pun">.</span><span class="typ">Enabled</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">False</span><span class="pln">
        ctSecs </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="str">'</span><span class="pln">clear count
        </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Interval</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1000</span><span class="pln"> </span><span class="str">'</span><span class="pln">one second in ms</span><span class="pun">.</span><span class="pln">
        </span><span class="str">'</span><span class="pln">start timers
        stpw</span><span class="pun">.</span><span class="typ">Reset</span><span class="pun">()</span><span class="pln">
        stpw</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">()</span><span class="pln">
        </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">()</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">

    </span><span class="typ">Dim</span><span class="pln"> stpw </span><span class="typ">As</span><span class="pln"> </span><span class="typ">New</span><span class="pln"> </span><span class="typ">Stopwatch</span><span class="pln">
    </span><span class="typ">Dim</span><span class="pln"> ctSecs </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Integer</span><span class="pln">

    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Timer1_Tick</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Tick</span><span class="pln">
        ctSecs </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
        </span><span class="typ">If</span><span class="pln"> ctSecs </span><span class="pun">=</span><span class="pln"> </span><span class="lit">180</span><span class="pln"> </span><span class="typ">Then</span><span class="pln"> </span><span class="str">'</span><span class="pln">about </span><span class="lit">2.5</span><span class="pln"> seconds off on my PC</span><span class="pun">!</span><span class="pln">
            </span><span class="str">'</span><span class="pln">stop timing
            stpw</span><span class="pun">.</span><span class="typ">Stop</span><span class="pun">()</span><span class="pln">
            </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Stop</span><span class="pun">()</span><span class="pln">
            </span><span class="str">'</span><span class="pln">show actual elapsed time
            </span><span class="str">'</span><span class="typ">Is</span><span class="pln"> it near </span><span class="lit">180</span><span class="pun">?</span><span class="pln">
            </span><span class="typ">Label1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> stpw</span><span class="pun">.</span><span class="typ">Elapsed</span><span class="pun">.</span><span class="typ">TotalSeconds</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(</span><span class="str">"n1"</span><span class="pun">)</span><span class="pln">
        </span><span class="typ">End</span><span class="pln"> </span><span class="typ">If</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">

</span><span class="typ">End</span><span class="pln"> </span><span class="typ">Class</span></pre>

<p>
	قد تَفترِض أنها لابُدّ وأن تكون مساوية للقيمة 180؟ في الواقع، ليس هذا ضروريًا. مثلًا قد عَرَضَ حاسوبي القيمة 182.5.
</p>

<p>
	السبب وراء هذا التفاوت هو أن عنصر <a href="https://msdn.microsoft.com/en-us/library/system.windows.forms.timer(v=vs.110).aspx" rel="external nofollow">المؤقت <code>Windows.Forms.Timer</code></a> أحادي الخيط (single-threaded)، ومحدود بدقة تصل إلى 55 ميللي ثانية، مما يعني أنه غير ملائم لتسجيل الزمن وتدقيقه، ولا ينبغي استخدامه لأغراض حساسة جدًا للزمن.
</p>

<p>
	يُمكن الحصول على نتائج أفضل باستخدام المؤقت وساعة الإيقاف بطريقة مختلفة، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1472_15" style="">
<span class="typ">Public</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="typ">Form1</span><span class="pln">

    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Button1_Click</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">Button1</span><span class="pun">.</span><span class="typ">Click</span><span class="pln">
        </span><span class="typ">Button1</span><span class="pun">.</span><span class="typ">Enabled</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">False</span><span class="pln">
        </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Interval</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100</span><span class="pln"> </span><span class="str">'</span><span class="pln">one tenth of a second in ms</span><span class="pun">.</span><span class="pln">
        </span><span class="str">'</span><span class="pln">start timers
        stpw</span><span class="pun">.</span><span class="typ">Reset</span><span class="pun">()</span><span class="pln">
        stpw</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">()</span><span class="pln">
        </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">()</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">

    </span><span class="typ">Dim</span><span class="pln"> stpw </span><span class="typ">As</span><span class="pln"> </span><span class="typ">New</span><span class="pln"> </span><span class="typ">Stopwatch</span><span class="pln">
    </span><span class="typ">Dim</span><span class="pln"> threeMinutes </span><span class="typ">As</span><span class="pln"> </span><span class="typ">TimeSpan</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TimeSpan</span><span class="pun">.</span><span class="typ">FromMinutes</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln">

    </span><span class="typ">Private</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln"> </span><span class="typ">Timer1_Tick</span><span class="pun">(</span><span class="pln">sender </span><span class="typ">As</span><span class="pln"> </span><span class="typ">Object</span><span class="pun">,</span><span class="pln"> e </span><span class="typ">As</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Handles</span><span class="pln"> </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Tick</span><span class="pln">
        </span><span class="typ">If</span><span class="pln"> stpw</span><span class="pun">.</span><span class="typ">Elapsed</span><span class="pln"> </span><span class="pun">&gt;=</span><span class="pln"> threeMinutes </span><span class="typ">Then</span><span class="pln"> </span><span class="str">'</span><span class="lit">0.1</span><span class="pln"> off on my PC</span><span class="pun">!</span><span class="pln">
            </span><span class="str">'</span><span class="pln">stop timing
            stpw</span><span class="pun">.</span><span class="typ">Stop</span><span class="pun">()</span><span class="pln">
            </span><span class="typ">Timer1</span><span class="pun">.</span><span class="typ">Stop</span><span class="pun">()</span><span class="pln">
            </span><span class="str">'</span><span class="pln">show actual elapsed time
            </span><span class="str">'</span><span class="pln">how close</span><span class="pun">?</span><span class="pln">
            </span><span class="typ">Label1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> stpw</span><span class="pun">.</span><span class="typ">Elapsed</span><span class="pun">.</span><span class="typ">TotalSeconds</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(</span><span class="str">"n1"</span><span class="pun">)</span><span class="pln">
        </span><span class="typ">End</span><span class="pln"> </span><span class="typ">If</span><span class="pln">
    </span><span class="typ">End</span><span class="pln"> </span><span class="typ">Sub</span><span class="pln">

</span><span class="typ">End</span><span class="pln"> </span><span class="typ">Class</span></pre>

<p>
	يوجد مؤقتات أخرى يمكن اِستخدَامها. قد تُساعِدك <a href="https://social.msdn.microsoft.com/Search/en-US?query=vb%20.net%20windows%20timers&amp;emptyWatermark=true&amp;searchButtonTooltip=Search%20MSDN&amp;ac=5#refinementChanges=117&amp;pageNumber=1&amp;showMore=false" rel="external nofollow">نتائج هذا البحث</a> بهذا الخصوص.
</p>

<h2>
	بعض النصائح للمبتدئين
</h2>

<p>
	نَستعرِض بعض النصائح التي ينبغي أن يَتبِعهَا المبتدئون حتى يحصلوا على بداية موفقة مع <code>VB.NET</code>:
</p>

<ul>
<li>
		اضبط الخيارات التالية:
	</li>
</ul>
<pre class="ipsCode">
'can be permanently set
' Tools / Options / Projects and Soluntions / VB Defaults
Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
End Class
</pre>

<ul>
<li>
		<p>
			<a href="https://msdn.microsoft.com/en-us/library/te2585xw.aspx?f=255&amp;MSPPError=-2147217396" rel="external nofollow">اِستخدِم العامل &amp; وليس + لضم السَلاسَل النصية</a>. عامةً ينبغي دراسة <a href="https://msdn.microsoft.com/en-us/library/system.string(v=vs.110).aspx" rel="external nofollow">النوع <code>String</code></a> بشئ من التفصيل نظرًا للحاجة إلى استخدامه بكثرة.
		</p>
	</li>
	<li>
		<p>
			اقض بعض الوقت لاستيعاب <a href="https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx" rel="external nofollow">الفرق بين أنواع القيمة وأنواع المَرجِع</a>.
		</p>
	</li>
	<li>
		<p>
			لا تَستخدِم التابع <code>Application.DoEvents</code> أبدًا. ألق نظرة على الفقرة التنبيهية بالرابط. عندما تكون متأكدًا من حاجتك الماسة لاستخدامه، اسأل.
		</p>
	</li>
	<li>
		<p>
			<a href="https://social.msdn.microsoft.com/Search/en-US?query=vb%20.net&amp;emptyWatermark=true&amp;searchButtonTooltip=Search%20MSDN&amp;ac=2" rel="external nofollow">التوثيق</a> هو رفيق دربك.
		</p>
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل VB Forms من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1002</guid><pubDate>Thu, 17 Sep 2020 12:53:54 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x634;&#x62E;&#x64A;&#x635; Diagnostics &#x641;&#x64A; dot Net</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%AA%D8%B4%D8%AE%D9%8A%D8%B5-diagnostics-%D9%81%D9%8A-dot-net-r1001/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/23.png.23b7a33bdc1ce73169fa3d42c917e24b.png" /></p>

<p>
	يُوفِّر فضاء الاسم <code>System.Diagnostics</code> العديد من الأصناف بهَدَف التَشخِيص، مثال أصناف للتَعامُل مع عمليات النظام (processes)، وأُخرى تَعمَل كعَدادات لقياس الأداء.
</p>

<h2>
	أوامر الصدفة (shell commands)
</h2>

<h3>
	تنفيذ أوامر الصَّدَفَة
</h3>

<p>
	يُستخدَم التابع <code>Process.Start</code> لتَّنْفيذ أمر صَّدَفَة (shell commands) تَّنْفيذًا برمجيًا. يتم ذلك من خلال إرساله للأمر المُمرَّر إليه إلى برنامج سطر الأوامر <code>cmd.exe</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_7" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Diagnostics</span><span class="pun">;</span><span class="pln">

string strCmdText </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/C copy /b Image1.jpg + Archive.rar Image2.jpg"</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Process</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">(</span><span class="str">"CMD.exe"</span><span class="pun">,</span><span class="pln">strCmdText</span><span class="pun">);</span></pre>

<p>
	تَتحَكَم الخاصية <code>WindowStyle</code> بحالة نافذة سطر الأوامر (cmd) عند تَّنْفيذ الأمر، فمثلًا يُمكِن إخفائها كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_9" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Diagnostics</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Process</span><span class="pln"> process </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Process</span><span class="pun">();</span><span class="pln">

</span><span class="typ">ProcessStartInfo</span><span class="pln"> startInfo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ProcessStartInfo</span><span class="pun">();</span><span class="pln">
startInfo</span><span class="pun">.</span><span class="typ">WindowStyle</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ProcessWindowStyle</span><span class="pun">.</span><span class="typ">Hidden</span><span class="pun">;</span><span class="pln">
startInfo</span><span class="pun">.</span><span class="typ">FileName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"cmd.exe"</span><span class="pun">;</span><span class="pln">
startInfo</span><span class="pun">.</span><span class="typ">Arguments</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/C copy /b Image1.jpg + Archive.rar Image2.jpg"</span><span class="pun">;</span><span class="pln">

process</span><span class="pun">.</span><span class="typ">StartInfo</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> startInfo</span><span class="pun">;</span><span class="pln">

process</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span></pre>

<h3>
	إرسال أوامر إلى سطر الأوامر واستقبال خرجها
</h3>

<p>
	يُعيد التابع <code>SendCommand</code> -المُعرَّف بالمثال التالي- سِلسِلة نصية تتَضمَن مُحتوَى كلًا من مَجْرى الخَرْج القياسي (STDOUT) ومَجْرى الخَطأ القياسي (STDERR) بعد تَّنْفيذ أمر صدَفَة، بالاعتماد على الحَدَثين <code>OutputDataReceived</code> و <code>ErrorDataReceived</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_11" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">SendCommand</span><span class="pun">(</span><span class="pln">string command</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var cmdOut </span><span class="pun">=</span><span class="pln"> string</span><span class="pun">.</span><span class="typ">Empty</span><span class="pun">;</span><span class="pln">

    var startInfo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ProcessStartInfo</span><span class="pun">(</span><span class="str">"cmd"</span><span class="pun">,</span><span class="pln"> command</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">WorkingDirectory</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">@</span><span class="str">"C:\Windows\System32"</span><span class="pun">,</span><span class="pln"> 
        </span><span class="typ">WindowStyle</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ProcessWindowStyle</span><span class="pun">.</span><span class="typ">Hidden</span><span class="pun">,</span><span class="pln"> </span><span class="com">// لإخفاء نافذة سطر الأوامر</span><span class="pln">
        </span><span class="typ">UseShellExecute</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="com">// لا تستخدم طرفية نظام التشغيل لبدء العملية</span><span class="pln">
        </span><span class="typ">CreateNoWindow</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="com">// ابدأ العملية بنافذة جديدة</span><span class="pln">
        </span><span class="typ">RedirectStandardOutput</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> </span><span class="com">// مطلوب لإتاحة مجرى الخرج القياسي</span><span class="pln">
        </span><span class="typ">RedirectStandardError</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pln"> </span><span class="com">// مطلوب لإتاحة مجرى الخطأ القياسي</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    var p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Process</span><span class="pln"> </span><span class="pun">{</span><span class="typ">StartInfo</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> startInfo</span><span class="pun">};</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">OutputDataReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> cmdOut </span><span class="pun">+=</span><span class="pln"> y</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">;</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">ErrorDataReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> cmdOut </span><span class="pun">+=</span><span class="pln"> y</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">;</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">BeginOutputReadLine</span><span class="pun">();</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">BeginErrorReadLine</span><span class="pun">();</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">WaitForExit</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> cmdOut</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُمكِن استدعاء التابع بالأعلى كالآتي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_13" style="">
<span class="pln">var servername </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SVR-01.domain.co.za"</span><span class="pun">;</span><span class="pln">
var currentUsers </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SendCommand</span><span class="pun">(</span><span class="pln">$</span><span class="str">"/C QUERY USER /SERVER:{servername}"</span><span class="pun">)</span></pre>

<p>
	يَكُون الخَرْج كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_15" style="">
<span class="pln">string currentUsers </span><span class="pun">=</span><span class="pln"> </span><span class="str">"USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME Joe.Bloggs ica-cgp#0 2 Active 24692+13:29 25/07/2016 07:50 Jim.McFlannegan ica-cgp#1 3 Active . 25/07/2016 08:33 Andy.McAnderson ica-cgp#2 4 Active . 25/07/2016 08:54 John.Smith ica-cgp#4 5 Active 14 25/07/2016 08:57 Bob.Bobbington ica-cgp#5 6 Active 24692+13:29 25/07/2016 09:05 Tim.Tom ica-cgp#6 7 Active . 25/07/2016 09:08 Bob.Joges ica-cgp#7 8 Active 24692+13:29 25/07/2016 09:13"</span></pre>

<p>
	<strong>ملحوظة</strong>:
</p>

<p>
	سيُعيد التابع المُعرَّف بالأعلى مُحتوَى كلًا من مَجْرى الخَرْج القياسي (STDOUT) ومَجْرى الخٍَطأ القياسي (STDERR) مَضْمومين بسِلسِلة نصية واحدة؛ حيث يُلحِق كلًا من الحَدَثين <code>OutputDataReceived</code> و <code>ErrorDataReceived</code> البيانات المُستلَمة إلى نفس المُتَغيّر <code>cmdOut</code>.
</p>

<p>
	يَقتصِر أحيانًا الولوج إلى الخادم المَعنِّى على مُستخدِمين بعينهم. إذا كان لديك بيانات دخول مُستخدِم مُعين، فمن المُمكن أن تُرسِل اِستعلامات (queries) إلى ذلك الخادم كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_17" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">SendCommand</span><span class="pun">(</span><span class="pln">string command</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var cmdOut </span><span class="pun">=</span><span class="pln"> string</span><span class="pun">.</span><span class="typ">Empty</span><span class="pun">;</span><span class="pln">

    var startInfo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ProcessStartInfo</span><span class="pun">(</span><span class="str">"cmd"</span><span class="pun">,</span><span class="pln"> command</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">WorkingDirectory</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">@</span><span class="str">"C:\Windows\System32"</span><span class="pun">,</span><span class="pln">
        </span><span class="com">// This does not actually work in conjunction with "runas" - the console window will still appear!</span><span class="pln">
        </span><span class="typ">WindowStyle</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ProcessWindowStyle</span><span class="pun">.</span><span class="typ">Hidden</span><span class="pun">,</span><span class="pln"> 
        </span><span class="typ">UseShellExecute</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">CreateNoWindow</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">RedirectStandardOutput</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">RedirectStandardError</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">Verb</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"runas"</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">Domain</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"doman1.co.za"</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">UserName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"administrator"</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">Password</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetPassword</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    var p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Process</span><span class="pln"> </span><span class="pun">{</span><span class="typ">StartInfo</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> startInfo</span><span class="pun">};</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">OutputDataReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> cmdOut </span><span class="pun">+=</span><span class="pln"> y</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">;</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">ErrorDataReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> cmdOut </span><span class="pun">+=</span><span class="pln"> y</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">;</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">BeginOutputReadLine</span><span class="pun">();</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">BeginErrorReadLine</span><span class="pun">();</span><span class="pln">
    p</span><span class="pun">.</span><span class="typ">WaitForExit</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> cmdOut</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التابع <code>GetPassword</code> لجلْب كلمة السر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_19" style="">
<span class="kwd">static</span><span class="pln"> </span><span class="typ">SecureString</span><span class="pln"> </span><span class="typ">GetPassword</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var plainText </span><span class="pun">=</span><span class="pln"> </span><span class="str">"password123"</span><span class="pun">;</span><span class="pln">
    var ss </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SecureString</span><span class="pun">();</span><span class="pln">
    foreach </span><span class="pun">(</span><span class="kwd">char</span><span class="pln"> c in plainText</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        ss</span><span class="pun">.</span><span class="typ">AppendChar</span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> ss</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	ضبط الإعداد ProcessThread.ProcessorAffinity
</h3>

<p>
	تُعبر الخاصية <code>ProcessorAffinity</code> من النوع <code>IntPtr</code> عن المُعالج (processor) الذي يُنفِّذ خيط العملية (process thread). يَعتمِد هذا الإعداد افتراضيًا على عدد مُعالِجات الحاسوب.
</p>

<p>
	اِستخدِم الشيفرة التالية لجَلْب خاصية <code>ProcessorAffinity</code> لعملية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_21" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">GetProcessAffinityMask</span><span class="pun">(</span><span class="pln">string processName </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Process</span><span class="pln"> myProcess </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetProcessByName</span><span class="pun">(</span><span class="pln">ref processName</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> processorAffinity </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln">myProcess</span><span class="pun">.</span><span class="typ">ProcessorAffinity</span><span class="pun">;</span><span class="pln">

    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Process {0} Affinity Mask is : {1}"</span><span class="pun">,</span><span class="pln"> processName</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FormatAffinity</span><span class="pun">(</span><span class="pln">processorAffinity</span><span class="pun">));</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> processorAffinity</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Process</span><span class="pln"> </span><span class="typ">GetProcessByName</span><span class="pun">(</span><span class="pln">ref string processName</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Process</span><span class="pln"> myProcess</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">string</span><span class="pun">.</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="pln">processName</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        myProcess </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Process</span><span class="pun">.</span><span class="typ">GetCurrentProcess</span><span class="pun">();</span><span class="pln">
        processName </span><span class="pun">=</span><span class="pln"> myProcess</span><span class="pun">.</span><span class="typ">ProcessName</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Process</span><span class="pun">[]</span><span class="pln"> processList </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Process</span><span class="pun">.</span><span class="typ">GetProcessesByName</span><span class="pun">(</span><span class="pln">processName</span><span class="pun">);</span><span class="pln">
        myProcess </span><span class="pun">=</span><span class="pln"> processList</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> myProcess</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">FormatAffinity</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> affinity</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Convert</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(</span><span class="pln">affinity</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">.</span><span class="typ">PadLeft</span><span class="pun">(</span><span class="typ">Environment</span><span class="pun">.</span><span class="typ">ProcessorCount</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُستخدَم كالآتي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_23" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">GetProcessAffinityMask</span><span class="pun">();</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخَرْج:
</p>

<pre class="ipsCode">
// Output:
// Process Test.vshost Affinity Mask is : 11111111
</pre>

<p>
	اِستخدِم الشيفرة التالية لضبط خاصية <code>ProcessorAffinity</code> لعملية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_26" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SetProcessAffinityMask</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> affinity</span><span class="pun">,</span><span class="pln"> string processName </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Process</span><span class="pln"> myProcess </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetProcessByName</span><span class="pun">(</span><span class="pln">ref processName</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Process {0} Old Affinity Mask is : {1}"</span><span class="pun">,</span><span class="pln"> processName</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FormatAffinity</span><span class="pun">((</span><span class="typ">int</span><span class="pun">)</span><span class="pln">myProcess</span><span class="pun">.</span><span class="typ">ProcessorAffinity</span><span class="pun">));</span><span class="pln">

        myProcess</span><span class="pun">.</span><span class="typ">ProcessorAffinity</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">IntPtr</span><span class="pun">(</span><span class="pln">affinity</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Process {0} New Affinity Mask is : {1}"</span><span class="pun">,</span><span class="pln"> processName</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FormatAffinity</span><span class="pun">((</span><span class="typ">int</span><span class="pun">)</span><span class="pln">myProcess</span><span class="pun">.</span><span class="typ">ProcessorAffinity</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يُستخدَم كالآتي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_28" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
 </span><span class="typ">int</span><span class="pln"> newAffinity </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Convert</span><span class="pun">.</span><span class="typ">ToInt32</span><span class="pun">(</span><span class="str">"10101010"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
 </span><span class="typ">SetProcessAffinityMask</span><span class="pun">(</span><span class="pln">newAffinity</span><span class="pun">);</span><span class="pln">
 </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخَرْج:
</p>

<pre class="ipsCode">
// Output :
// Process Test.vshost Old Affinity Mask is : 11111111
// Process Test.vshost New Affinity Mask is : 10101010
</pre>

<h2>
	قياس الأداء باستخدام النوع <code>Stopwatch</code>
</h2>

<p>
	يُمكِن اِستخدَام النوع <code>Stopwatch</code> بفضاء الاسم <code>System.Diagnostics</code> لقياس أداء (benchmark) كُتلة من الشيفرة، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_30" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Diagnostics</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Benchmark</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IDisposable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="typ">Stopwatch</span><span class="pln"> sw</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Benchmark</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        sw </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Stopwatch</span><span class="pun">.</span><span class="typ">StartNew</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Dispose</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        sw</span><span class="pun">.</span><span class="typ">Stop</span><span class="pun">();</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">sw</span><span class="pun">.</span><span class="typ">Elapsed</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var bench </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Benchmark</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	مواصفات اصطلاحية للشيفرة (code contracts)
</h2>

<p>
	يُوفِّر فضاء الاسم <code>System.Diagnostics.Contracts</code> العديد من الأصناف لتَعزيز الشيفرة الخاصة بك بمزيد من الشروط (conditions) اللازم تَحقيقها إمّا خلال وقت التَصْريف أو التَّنْفيذ، مما يُحسِن من فَحْص الشيفرة واكتشاف الأخطاء.
</p>

<h3>
	تثبيت المواصفات الاصطلاحية للشيفرة وتفعيلها
</h3>

<p>
	يأتي فضاء الاسم <code>System.Diagnostics.Contracts</code> ضِمْن إطار عمل ‎.NET. لكن ما زلت في حَاجة إلى تَثْبيت الإضافة <code>Code Contracts Tools</code> ببيئة التطوير المتكاملة فيجوال ستوديو (Visual Studio IDE) حتى تستطيع اِستخدَام المُواصَفَات الاصطلاحيّة للشيفرة (code contracts).
</p>

<p>
	يُمكنك البحث عن <code>Code Contracts</code> بنافذة الإضافات والتحديثات <code>Extensions and Updates</code> بفيجوال ستوديو.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2020_09/002Install_Code_Contracts_Tools.png.22f26d867804d3859353978877141423.png" data-fileid="51128" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="51128" data-unique="96gljii2l" src="https://academy.hsoub.com/uploads/monthly_2020_09/002Install_Code_Contracts_Tools.thumb.png.372af2d9aa78644dc896b4f8d565202f.png" alt="002Install_Code_Contracts_Tools.png"></a>
</p>

<p>
	يجب أن تُفعِّل خاصية المُواصَفَات الاصطلاحيّة للشيفرة (code contracts) بحل المشروع بعد الإنتهاء من تَثْبيت الإضافة.
</p>

<p>
	تحتاج إلى تَّفْعِيل خاصية الفَحْص الساكن (Static Checking) -فَحْص ما بعد البناء (build)- على الأقل. قد تَرغَب أيضًا بتَّفْعِيل خاصية الفَحْص أثناء التشغيل (Runtime Checking) بالتحديد إذا كنت تُطَوِّر مكتبة (library) ستُستَعَمَل من قِبل حلول (solutions) أُخرى.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2020_09/003Configure_Code_Contracts_Tools.png.1c6c4e74b86a62018de0caa6c55c4ba7.png" data-fileid="51129" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="51129" data-unique="5v99l1kji" src="https://academy.hsoub.com/uploads/monthly_2020_09/003Configure_Code_Contracts_Tools.thumb.png.ddf8875d8ed61abd471011278e7d6b6c.png" alt="003Configure_Code_Contracts_Tools.png"></a>
</p>

<h3>
	الشروط المسبقة (Preconditions)
</h3>

<p>
	يَضمَن استخدام الشروط المُسبَقة للتوابع (preconditions) الحد الأدنى من مُتطلَّبات قيم مُعامِلات الدَخْل لتلك التوابع. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_34" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">DoWork</span><span class="pun">(</span><span class="pln">string input</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Contract</span><span class="pun">.</span><span class="typ">Requires</span><span class="pun">(!</span><span class="pln">string</span><span class="pun">.</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="pln">input</span><span class="pun">));</span><span class="pln">


    </span><span class="com">//do work</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نتائج تحليل الفَحْص الساكن:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="51130" data-unique="vbrtftxmz" src="https://academy.hsoub.com/uploads/monthly_2020_09/004Precondition_Static_Analysis_Result.png.386e7ec0121404fdf48080afee88b24f.png" alt="004Precondition_Static_Analysis_Result.png"></p>

<h3>
	الشروط اللاحقة (Postconditions)
</h3>

<p>
	يَضمَن اِستخدَام الشروط اللاحقة للتوابع (postconditions) تَوَافُق النتائج التي تُعيدها تلك التوابع مع التَعرِيف المُخصص للنتائج المتوقعة. يُساعد ذلك على تنْفيذ مُبسَط من خلال إمداد المُحلِّل الساكن (static analyizer) بالعديد من النتائج المُحتَملة. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_32" style="">
<span class="pln">string </span><span class="typ">GetValue</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Contract</span><span class="pun">.</span><span class="typ">Ensures</span><span class="pun">(</span><span class="typ">Contract</span><span class="pun">.</span><span class="typ">Result</span><span class="str">&lt;string&gt;</span><span class="pun">()</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">);</span><span class="pln">


    </span><span class="kwd">return</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نتائج تحليل الفَحْص الساكن:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="51131" data-unique="3brr54uj7" src="https://academy.hsoub.com/uploads/monthly_2020_09/005Postcondition_Static_Analysis_Result.png.ae60d4ff6224ad1c02eac242b7d51a2b.png" alt="005Postcondition_Static_Analysis_Result.png"></p>

<h3>
	إضافة مواصفات اصطلاحيّة للشيفرة إلى الواجهات (interfaces)
</h3>

<p>
	يُمكِن أيضًا فَرْض مُواصَفَات اصطلاحيّة للشيفرة (code contracts) على وَاجِهة (interface) عن طريق الإعلان عن صنف مُجرَّد (abstract class) يُنفِّذ هذه الواجهة بشرط أن تُزخرَف الواجهة والصنف المُجرَّد بالسمتين <code>ContractClassAttribute</code> و <code>ContractClassForAttribute</code> على الترتيب. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8487_36" style="">
<span class="pun">[</span><span class="typ">ContractClass</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">MyInterfaceContract</span><span class="pun">))]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> interface </span><span class="typ">IMyInterface</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    string </span><span class="typ">DoWork</span><span class="pun">(</span><span class="pln">string input</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">[</span><span class="typ">ContractClassFor</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">IMyInterface</span><span class="pun">))]</span><span class="pln">
internal abstract </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyInterfaceContract</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IMyInterface</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="typ">MyInterfaceContract</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">DoWork</span><span class="pun">(</span><span class="pln">string input</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Contract</span><span class="pun">.</span><span class="typ">Requires</span><span class="pun">(!</span><span class="pln">string</span><span class="pun">.</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="pln">input</span><span class="pun">));</span><span class="pln">
        </span><span class="typ">Contract</span><span class="pun">.</span><span class="typ">Ensures</span><span class="pun">(!</span><span class="pln">string</span><span class="pun">.</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="typ">Contract</span><span class="pun">.</span><span class="typ">Result</span><span class="str">&lt;string&gt;</span><span class="pun">()));</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">NotSupportedException</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyInterfaceImplmentation</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IMyInterface</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">DoWork</span><span class="pun">(</span><span class="pln">string input</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> input</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال بالأعلى، تُعلِّن الواجهة <code>IMyInterface</code> عن التابع <code>DoWork</code> الذي يَستقبِل مُعامِلًا من النوع <code>string</code>. في الحالة العادية، يُمكنك أن تُمرِّر القيمة الفارغة <code>null</code> إليه. لكن لا يُصبِح ذلك مُمكنًا بعد إضافة المُواصفة الإصطلاحيّة بالأعلى والتي تَستخدِم التابع <code>Contract.Requires</code> لفَرْض شرط مُسبَق (precondition) بألا يَكون المُعامِل المُمرّر فارغًا.
</p>

<p>
	نتائج تحليل الفَحْص الساكن:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="51127" data-unique="j95aofje4" src="https://academy.hsoub.com/uploads/monthly_2020_09/001Example_Result.png.6620aa70947fb9b4ad5b2077288163b1.png" alt="001Example_Result.png"></p>

<p>
	ترجمة -وبتصرف- للفصول System.Diagnostics - Code Contracts - Process and Thread Affinity setting من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1001</guid><pubDate>Thu, 17 Sep 2020 12:48:09 +0000</pubDate></item><item><title>&#x627;&#x644;&#x634;&#x62C;&#x631;&#x629; &#x627;&#x644;&#x62A;&#x639;&#x628;&#x64A;&#x631;&#x64A;&#x629; Expression Tree &#x641;&#x64A; dot Net</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%B4%D8%AC%D8%B1%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A8%D9%8A%D8%B1%D9%8A%D8%A9-expression-tree-%D9%81%D9%8A-dot-net-r1000/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/22.png.da9e5526fde36106bd79ee603fb296a9.png" /></p>

<p>
	تُستخدَم الشجرة التعبيرية (Expression Tree) عند الحاجة لإنشاء تعبيرات (expressions) خلال زمن التشغيل (runtime)، مما يجعلها مناسبة للأغراض التالية:
</p>

<ul>
<li>
		مع الواجهات <code>IEnumerable</code> و <code>IQueryable</code> لفَحْص خَبَر (predicate) معين.
	</li>
	<li>
		مع <code>Entity Framework</code> أو <code>LINQ to SQL</code> لتنشئة عبارة <code>Where</code> لفَحْص خَبَر معين.
	</li>
</ul>
<p>
	يُمكِن إنشاء شجرة تعبيرية (Expression Tree) بطريقتين أساسيتين:
</p>

<p>
	الأولى: اِستخدَام واجهة برمجة التطبيقات (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) الخاصة بالنوع <code>Expression</code> (طريقة يدوية). الثانية: إِسْناد دالة مُجرَّدة (lambda expression) إلى مُتغيّر من النوع <code>Expression</code> (طريقة مُولدَّة آليًا).
</p>

<h2>
	إنشاء النوع <code>BinaryExpression</code> باستخدام واجهة برمجة التطبيقات
</h2>

<p>
	على سبيل المثال، إذا كان لديك كُلًا من الخَبَر <code>‎_ ‎=&gt; ‎_.‎‎Field‎</code> وسِلسِلة نصية تَحمِل القيمة "VALUE"، يُمكِنك إنشاء التعبير <code>‎_ =&gt; _.Field == "VALUE"‎</code> أثناء زمن التشغيل (runtime) لفَحْص قيمة الخَبَر.
</p>

<p>
	في الشيفرة التالية، عُرِّف التابع <code>BuildEqualPredicate</code> والذي يَستخدِم واجهة برمجة التطبيقات الخاصة بالصنف <code>Expression</code>، فيَستدعِي التابع <code>Expression.Equal</code> ليُنشِئ شجرة تعبيرية من النوع <code>BinaryExpression</code> تَفحَص ما إذا كانت قيمة المُتغيّر <code>Field</code> مُساوية للسِلسِلة النصية "VALUE":
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_7" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">BuildEqualPredicate</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="pln">
    </span><span class="typ">Expression</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;&gt;</span><span class="pln"> memberAccessor</span><span class="pun">,</span><span class="pln">
    string term</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var toString </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Convert</span><span class="pun">(</span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Constant</span><span class="pun">(</span><span class="pln">term</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">string</span><span class="pun">));</span><span class="pln">
    </span><span class="typ">Expression</span><span class="pln"> expression </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Equal</span><span class="pun">(</span><span class="pln">memberAccessor</span><span class="pun">.</span><span class="typ">Body</span><span class="pun">,</span><span class="pln"> toString</span><span class="pun">);</span><span class="pln">
    var predicate </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Lambda</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">&gt;&gt;(</span><span class="pln">
        expression</span><span class="pun">,</span><span class="pln">
        memberAccessor</span><span class="pun">.</span><span class="typ">Parameters</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> predicate</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُمكن تَمرير الخَبَر المُنشَئ (predicate) كمُعامِل للتابع المُوسِع <code>Where</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_9" style="">
<span class="pln">var predicate </span><span class="pun">=</span><span class="pln"> </span><span class="typ">PredicateExtensions</span><span class="pun">.</span><span class="typ">BuildEqualPredicate</span><span class="pun">&lt;</span><span class="typ">Entity</span><span class="pun">&gt;(</span><span class="pln">
    _ </span><span class="pun">=&gt;</span><span class="pln"> _</span><span class="pun">.</span><span class="typ">Field</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"VALUE"</span><span class="pun">);</span><span class="pln">
var results </span><span class="pun">=</span><span class="pln"> context</span><span class="pun">.</span><span class="typ">Entity</span><span class="pun">.</span><span class="typ">Where</span><span class="pun">(</span><span class="pln">predicate</span><span class="pun">).</span><span class="typ">ToList</span><span class="pun">();</span></pre>

<h2>
	تنشئة النوع <code>LambdaExpression</code> بإسناد دالة مجردة إلى متغير من النوع <code>Expression</code>
</h2>

<p>
	عادةً ما تُسْنَد الدوال المُجرَّدة (lambda expressions) إلى مُتغيرات من النوع <code>Delegate</code> تَعمَل كمُفوِّض قابل للاستدعاء. في المُقابل، يُمكنك إِسنادها إلى مُتَغيّر من النوع <code>Expression</code>، وفي هذه الحالة، يُولِّد مُصرِّف C#‎ شجرة تعبيرية (Expression Tree) مُكافئة، فمثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_11" style="">
<span class="typ">Expression</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;&gt;</span><span class="pln"> expression </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">=&gt;</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span></pre>

<p>
	يُولَّد عن المثال بالأعلى شجرة تعبيرية (Expression Tree) من النوع <code>LambdaExpression</code> مُكافِئة للشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_13" style="">
<span class="typ">ParameterExpression</span><span class="pln"> parameterA </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Parameter</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln"> </span><span class="str">"a"</span><span class="pun">);</span><span class="pln">
var expression </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Expression</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;&gt;)</span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Lambda</span><span class="pun">(</span><span class="pln">
    </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">
        parameterA</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Constant</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)),</span><span class="pln">
    parameterA</span><span class="pun">);</span></pre>

<p>
	تُمثِل الشجرة التعبيرية من النوع <code>LambdaExpression</code> دالة مُجرَّدة تتكون من مَتْن الدالة body وقائمة المُتغيّرات. مثلًا، في المثال بالأعلى، تَستقبِل الدالة المُمثَّلة مُعامِلًا وحيدًا يُدعى a بينما يتكون المَتن من عبارة وحيدة من النوع <code>BinaryExpression</code> بخاصية <code>NodeType</code> من النوع <code>Add</code>. يُمثِل هذا التعبير بدوره عملية جَمع تتكون من تعبيرين فرعيين (sub-expressions) يُشار إليهما بالتعبيرين الأيمن والأيسر. التعبير الأيسر هو من النوع <code>ParameterExpression</code> يُمثِل المُعامِل a المُمرَّر، أما التعبير الأيمن فهو من النوع <code>ConstantExpression</code> بقيمة تساوي الواحد.
</p>

<p>
	أبسط ما يُمكنك القيام به هو طباعة قيمة التَعبير (expression)، والذي بدوره يَطبع شيفرة C#‎ المكافئة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_15" style="">
<span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">expression</span><span class="pun">);</span><span class="pln"> </span><span class="com">//prints a =&gt; (a + 1)</span></pre>

<p>
	يُستخدَم التابع <code>Compile</code> لتَصرِّيف الشجرة التعبيرية (expression tree) إلى مُتغيّر من النوع <code>Delegate</code>، قابل للاستدعاء ببيئة التَّنفيذ المُشتركة (CLR)، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_17" style="">
<span class="typ">Func</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> lambda </span><span class="pun">=</span><span class="pln"> expression</span><span class="pun">.</span><span class="typ">Compile</span><span class="pun">();</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">lambda</span><span class="pun">(</span><span class="lit">2</span><span class="pun">));</span><span class="pln"> </span><span class="com">//prints 3</span></pre>

<h2>
	إنشاء النوع <code>MemberExpression</code> باستخدام واجهة برمجة التطبيقات
</h2>

<p>
	عادةً ما تُترجَم التعبيرات (expressions) إلى لغات آخرى مثل SQL، لكن يُمكِن اِستخدَامها أيضًا لاستدعاء أعضاء الأصناف (members) سواء كانت هذه الأعضاء خاصة (private) أو (internal) أو (protected) وسواء ما كانت الأنواع عَلَّنية (public) أم لا، كطريقة بديلة للانعكاس (Reflection).
</p>

<p>
	بفرض أن لديك الصنف التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_19" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="typ">TestClass</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">StaticPublicField</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"StaticPublicFieldValue"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استرجاع قيمة الخاصية <code>StaticPublicField</code> الساكنة (static) كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_21" style="">
<span class="pln">var fieldExpr </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Field</span><span class="pun">(</span><span class="pln">null</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">TestClass</span><span class="pun">),</span><span class="pln"> </span><span class="str">"StaticPublicField"</span><span class="pun">);</span><span class="pln">
var labmda </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Lambda</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="str">&lt;string&gt;</span><span class="pun">&gt;(</span><span class="pln">fieldExpr</span><span class="pun">);</span></pre>

<p>
	يُمكن تَصرِيف الشجرة التعبيرية لمُفوِّض يُمكِن استدعائه للولوج لقيمة الخاصية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_23" style="">
<span class="typ">Func</span><span class="str">&lt;string&gt;</span><span class="pln"> retriever </span><span class="pun">=</span><span class="pln"> lambda</span><span class="pun">.</span><span class="typ">Compile</span><span class="pun">();</span><span class="pln">
var fieldValue </span><span class="pun">=</span><span class="pln"> retriever</span><span class="pun">();</span></pre>

<h2>
	إنشاء النوع <code>InvocationExpression</code> باستخدام واجهة برمجة التطبيقات
</h2>

<p>
	يُستخدَم التابع الساكن <code>Expression.Invoke</code> لإنشاء شجرة تعبيرية من النوع <code>InvocationExpression</code>. يُمَكِّنك هذا النوع من استدعاء دوال مُجرَّدة أُخرى (lambda expressions) مُضمنة بالشجرة التعبيرية ذاتها (Expression tree).
</p>

<p>
	المشكلة:
</p>

<p>
	نريد الوصول إلى العناصر التي تحتوي خاصية <code>Description</code> الخاصة بهم على السِلسِلة النصية "car". نحتاج إلى التأكد من أن تلك الخاصية ليست فارغة <code>null</code> قبل البحث فيها عن السِلسِلة النصية، لكن لا نريد أن نُفْرِط في استدعائها لأن الكلفة قد تكون عالية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_25" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Linq</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Linq</span><span class="pun">.</span><span class="typ">Expressions</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var elements </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Element</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Description</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"car"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Element</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Description</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"cargo"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Element</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Description</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"wheel"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Element</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Description</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> null </span><span class="pun">},</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Element</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Description</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Madagascar"</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">

        var elementIsInterestingExpression </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateSearchPredicate</span><span class="pun">(</span><span class="pln">
            searchTerm</span><span class="pun">:</span><span class="pln"> </span><span class="str">"car"</span><span class="pun">,</span><span class="pln">
            whereToSearch</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Element</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">Description</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">elementIsInterestingExpression</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">());</span><span class="pln">

        var elementIsInteresting </span><span class="pun">=</span><span class="pln"> elementIsInterestingExpression</span><span class="pun">.</span><span class="typ">Compile</span><span class="pun">();</span><span class="pln">
        var interestingElements </span><span class="pun">=</span><span class="pln"> elements</span><span class="pun">.</span><span class="typ">Where</span><span class="pun">(</span><span class="pln">elementIsInteresting</span><span class="pun">);</span><span class="pln">
        foreach </span><span class="pun">(</span><span class="pln">var e in interestingElements</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="typ">Description</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        var countExpensiveComputations </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">Action</span><span class="pln"> incCount </span><span class="pun">=</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> countExpensiveComputations</span><span class="pun">++;</span><span class="pln">
        elements
            </span><span class="pun">.</span><span class="typ">Where</span><span class="pun">(</span><span class="pln">
            </span><span class="typ">CreateSearchPredicate</span><span class="pun">(</span><span class="pln">
                </span><span class="str">"car"</span><span class="pun">,</span><span class="pln">
                </span><span class="pun">(</span><span class="typ">Element</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">ExpensivelyComputed</span><span class="pun">(</span><span class="pln">
                    e</span><span class="pun">,</span><span class="pln"> incCount
                </span><span class="pun">)</span><span class="pln">
            </span><span class="pun">).</span><span class="typ">Compile</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">)</span><span class="pln">
            </span><span class="pun">.</span><span class="typ">Count</span><span class="pun">();</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Property extractor is called {0} times."</span><span class="pun">,</span><span class="pln"> countExpensiveComputations</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Element</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Description</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">ExpensivelyComputed</span><span class="pun">(</span><span class="typ">Element</span><span class="pln"> source</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Action</span><span class="pln"> count</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        count</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> source</span><span class="pun">.</span><span class="typ">Description</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">CreateSearchPredicate</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">string searchTerm</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;&gt;</span><span class="pln"> whereToSearch</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var extracted </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Parameter</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">string</span><span class="pun">),</span><span class="pln"> </span><span class="str">"extracted"</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Expression</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">&gt;&gt;</span><span class="pln"> coalesceNullCheckWithSearch </span><span class="pun">=</span><span class="pln">
            </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Lambda</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">&gt;&gt;(</span><span class="pln">
            </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">AndAlso</span><span class="pun">(</span><span class="pln">
                </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Not</span><span class="pun">(</span><span class="pln">
                    </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Call</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">string</span><span class="pun">),</span><span class="pln"> </span><span class="str">"IsNullOrEmpty"</span><span class="pun">,</span><span class="pln"> null</span><span class="pun">,</span><span class="pln"> extracted</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">),</span><span class="pln">
                </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Call</span><span class="pun">(</span><span class="pln">extracted</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Contains"</span><span class="pun">,</span><span class="pln"> null</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Constant</span><span class="pun">(</span><span class="pln">searchTerm</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">),</span><span class="pln">
            extracted</span><span class="pun">);</span><span class="pln">

        var elementParameter </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Parameter</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">),</span><span class="pln"> </span><span class="str">"element"</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Lambda</span><span class="pun">&lt;</span><span class="typ">Func</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">&gt;&gt;(</span><span class="pln">
            </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Invoke</span><span class="pun">(</span><span class="pln">
                coalesceNullCheckWithSearch</span><span class="pun">,</span><span class="pln">
                </span><span class="typ">Expression</span><span class="pun">.</span><span class="typ">Invoke</span><span class="pun">(</span><span class="pln">whereToSearch</span><span class="pun">,</span><span class="pln"> elementParameter</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">),</span><span class="pln">
            elementParameter
        </span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخَرْج:
</p>

<pre class="ipsCode">
element =&gt; Invoke(
    extracted =&gt; (Not(IsNullOrEmpty(extracted)) AndAlso extracted.Contains("car")),
    Invoke(e =&gt; e.Description, element))
    car
    cargo
    Madagascar
    Predicate is called 5 times.
</pre>

<p>
	تم تَضمِين الولوج للخاصية <code>Description</code> بداخل التابع <code>Invoke</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_28" style="">
<span class="typ">Invoke</span><span class="pun">(</span><span class="pln">e </span><span class="pun">=&gt;</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">Description</span><span class="pun">,</span><span class="pln"> element</span><span class="pun">)</span></pre>

<p>
	وهذا هو المكان الوحيد الذي يتم التعامل فيه مع الخاصية <code>Description</code> مباشرة، فقد تم استخراج متُغير آخر من النوع <code>String</code> وتمريره للتابع التالي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_836_30" style="">
<span class="pun">(</span><span class="typ">Not</span><span class="pun">(</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="pln">extracted</span><span class="pun">))</span><span class="pln"> </span><span class="typ">AndAlso</span><span class="pln"> extracted</span><span class="pun">.</span><span class="typ">Contains</span><span class="pun">(</span><span class="str">"car"</span><span class="pun">))</span></pre>

<p>
	من المهم أن تكون على دراية بكيفية عمل العَامِل <code>AndAlso</code>. إذا آلت قيمة المُعامِل الأيسر للقيمة المنطقية <code>false</code>، فإن التابع <code>AndAlso</code> يُعيد نفس ذات القيمة <code>false</code> دون أن يحسِب قيمة المُعامِل الأيمن. يُعدّ استخدام العَامِل <code>And</code> أحد أكثر الأخطاء شيوعًا. فبالإضافة إلى حِسابه لقيمة كلا المُعامِلين دومًا بغض النظر عن قيمتهما، فإنه أيضًا قد يُبلِّغ عن اعتراض من النوع <code>NullReferenceException</code> إذا اُستخدِم بشكل مشابه للمثال بالأعلى.
</p>

<p>
	ترجمة -وبتصرف- للفصل Expression Trees من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">1000</guid><pubDate>Thu, 17 Sep 2020 12:40:10 +0000</pubDate></item><item><title>&#x636;&#x628;&#x637; &#x627;&#x644;&#x62E;&#x648;&#x627;&#x62F;&#x645; &#x648;&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x627;&#x644;&#x637;&#x644;&#x628;&#x64A;&#x627;&#x62A; &#x641;&#x64A; dot Net</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%B6%D8%A8%D8%B7-%D8%A7%D9%84%D8%AE%D9%88%D8%A7%D8%AF%D9%85-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%B7%D9%84%D8%A8%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-dot-net-r999/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/21.png.f819254883a471a48304fea9d10857ff.png" /></p>

<h2>
	خادم HTTP
</h2>

<h3>
	إنشاء خادم HTTP باستخدام الصنف HttpListener
</h3>

<p>
	يُستخدَم النوع <code>HttpListener</code> لإنشاء مُستمِع (listener) مُبسط للرد على طلبات HTTP. نُنشِئ نسخة من هذا النوع كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_7" style="">
<span class="pln">listener </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HttpListener</span><span class="pun">();</span></pre>

<p>
	تُستخدَم الخاصية <code>Prefixes</code> لتخصيص الرابط (url) الذي يَستمِع إليه الخادم والذي ستُرسَل إليه طلبات الـ HTTP.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_9" style="">
<span class="pln">listener</span><span class="pun">.</span><span class="typ">Prefixes</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="str">"http://*:"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> port </span><span class="pun">+</span><span class="pln"> </span><span class="str">"/"</span><span class="pun">);</span><span class="pln">
listener</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span></pre>

<p>
	عندما يَستلِم الخادم طَلَبًا (http request) مُعينًا، فإنه بالضرورة يحتاج إلى معلومات عن الطلب حتى يقوم بمُعالجته. تَتوَفر تلك المعلومات من خلال التابع <code>GetContext()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_11" style="">
<span class="pln">var context </span><span class="pun">=</span><span class="pln"> listener</span><span class="pun">.</span><span class="typ">GetContext</span><span class="pun">();</span><span class="pln">

var request </span><span class="pun">=</span><span class="pln"> context</span><span class="pun">.</span><span class="typ">Request</span><span class="pun">;</span><span class="pln">
response </span><span class="pun">=</span><span class="pln"> context</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">;</span></pre>

<p>
	نظرًا لأن الهدف من خادم الملفات هو إرسال الملفات عند طلبها، سيقوم الخادم أولًا بتحديد اسم الملف المطلوب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_13" style="">
<span class="pln">var fileName </span><span class="pun">=</span><span class="pln"> request</span><span class="pun">.</span><span class="typ">RawUrl</span><span class="pun">.</span><span class="typ">Substring</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span></pre>

<p>
	ثم يُرسِل مُحتويات الملف إلى مَجْرى مَتْن الرد (response body) كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_15" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var fileStream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">OpenRead</span><span class="pun">(</span><span class="pln">fullFilePath</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    response</span><span class="pun">.</span><span class="typ">ContentType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"application/octet-stream"</span><span class="pun">;</span><span class="pln">
    response</span><span class="pun">.</span><span class="typ">ContentLength64</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileInfo</span><span class="pun">(</span><span class="pln">fullFilePath</span><span class="pun">)).</span><span class="typ">Length</span><span class="pun">;</span><span class="pln">
    response</span><span class="pun">.</span><span class="typ">AddHeader</span><span class="pun">(</span><span class="str">"Content-Disposition"</span><span class="pun">,</span><span class="pln">
                       </span><span class="str">"Attachment; filename=\""</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">.</span><span class="typ">GetFileName</span><span class="pun">(</span><span class="pln">fullFilePath</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">"\""</span><span class="pun">);</span><span class="pln">
    fileStream</span><span class="pun">.</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">response</span><span class="pun">.</span><span class="typ">OutputStream</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

response</span><span class="pun">.</span><span class="typ">OutputStream</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span></pre>

<p>
	المثال بالكامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_17" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HttpFileServer</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">HttpListenerResponse</span><span class="pln"> response</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">HttpListener</span><span class="pln"> listener</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string baseFilesystemPath</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="typ">HttpListener</span><span class="pun">.</span><span class="typ">IsSupported</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">
                </span><span class="str">"*** HttpListener requires at least Windows XP SP2 or Windows Server 2003."</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">args</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Basic read-only HTTP file server"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Usage: httpfileserver &lt;base filesystem path&gt; &lt;port&gt;"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Request format: http://url:port/path/to/file.ext"</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        baseFilesystemPath </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">.</span><span class="typ">GetFullPath</span><span class="pun">(</span><span class="pln">args</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">

        var port </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="pln">args</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">

        listener </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HttpListener</span><span class="pun">();</span><span class="pln">
        listener</span><span class="pun">.</span><span class="typ">Prefixes</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="str">"http://*:"</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> port </span><span class="pun">+</span><span class="pln"> </span><span class="str">"/"</span><span class="pun">);</span><span class="pln">
        listener</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Server stated, base path is: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> baseFilesystemPath</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Listening, exit with Ctrl-C"</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">ServerLoop</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">ex</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">response </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">SendErrorResponse</span><span class="pun">(</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Internal server error"</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ServerLoop</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            var context </span><span class="pun">=</span><span class="pln"> listener</span><span class="pun">.</span><span class="typ">GetContext</span><span class="pun">();</span><span class="pln">
            var request </span><span class="pun">=</span><span class="pln"> context</span><span class="pun">.</span><span class="typ">Request</span><span class="pun">;</span><span class="pln">

            response </span><span class="pun">=</span><span class="pln"> context</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">;</span><span class="pln">

            var fileName </span><span class="pun">=</span><span class="pln"> request</span><span class="pun">.</span><span class="typ">RawUrl</span><span class="pun">.</span><span class="typ">Substring</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Got {0} request for: {1}"</span><span class="pun">,</span><span class="pln"> request</span><span class="pun">.</span><span class="typ">HttpMethod</span><span class="pun">,</span><span class="pln"> fileName</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">request</span><span class="pun">.</span><span class="typ">HttpMethod</span><span class="pun">.</span><span class="typ">ToUpper</span><span class="pun">()</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="str">"GET"</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">SendErrorResponse</span><span class="pun">(</span><span class="lit">405</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Method must be GET"</span><span class="pun">);</span><span class="pln">
                </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            var fullFilePath </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">.</span><span class="typ">Combine</span><span class="pun">(</span><span class="pln">baseFilesystemPath</span><span class="pun">,</span><span class="pln"> fileName</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">if</span><span class="pun">(!</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">fullFilePath</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">SendErrorResponse</span><span class="pun">(</span><span class="lit">404</span><span class="pun">,</span><span class="pln"> </span><span class="str">"File not found"</span><span class="pun">);</span><span class="pln">
                </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">" Sending file..."</span><span class="pun">);</span><span class="pln">

            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var fileStream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">OpenRead</span><span class="pun">(</span><span class="pln">fullFilePath</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                response</span><span class="pun">.</span><span class="typ">ContentType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"application/octet-stream"</span><span class="pun">;</span><span class="pln">
                response</span><span class="pun">.</span><span class="typ">ContentLength64</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileInfo</span><span class="pun">(</span><span class="pln">fullFilePath</span><span class="pun">)).</span><span class="typ">Length</span><span class="pun">;</span><span class="pln">
                response</span><span class="pun">.</span><span class="typ">AddHeader</span><span class="pun">(</span><span class="str">"Content-Disposition"</span><span class="pun">,</span><span class="pln">
                                   </span><span class="str">"Attachment; filename=\""</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">.</span><span class="typ">GetFileName</span><span class="pun">(</span><span class="pln">fullFilePath</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">"\""</span><span class="pun">);</span><span class="pln">
                fileStream</span><span class="pun">.</span><span class="typ">CopyTo</span><span class="pun">(</span><span class="pln">response</span><span class="pun">.</span><span class="typ">OutputStream</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            response</span><span class="pun">.</span><span class="typ">OutputStream</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span><span class="pln">
            response </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">

            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Ok!"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SendErrorResponse</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> statusCode</span><span class="pun">,</span><span class="pln"> string statusResponse</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        response</span><span class="pun">.</span><span class="typ">ContentLength64</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        response</span><span class="pun">.</span><span class="typ">StatusCode</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> statusCode</span><span class="pun">;</span><span class="pln">
        response</span><span class="pun">.</span><span class="typ">StatusDescription</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> statusResponse</span><span class="pun">;</span><span class="pln">
        response</span><span class="pun">.</span><span class="typ">OutputStream</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"*** Sent error: {0} {1}"</span><span class="pun">,</span><span class="pln"> statusCode</span><span class="pun">,</span><span class="pln"> statusResponse</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إنشاء خادم HTTP باستخدام ASP.NET Core
</h3>

<p>
	بالمثل، نُنشِئ خادم ببروتوكول HTTP لقراءة الملفات (file server) مُشابه للمثال بالأعلى لكن باستخدام بيئة عمل <code>ASP.NET Core</code> المتطورة.
</p>

<p>
	أولًا: اِنشِئ مجلد فارغ، سنُضيف إليه ملفات المشروع المُنشئة خلال الخطوات التالية.
</p>

<p>
	ثانيًا: اِنشِئ ملف باسم <code>project.json</code> وأَضِف إليه المحتويات التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_19" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="str">"dependencies"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"Microsoft.AspNet.Server.Kestrel"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"1.0.0-rc1-final"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"Microsoft.AspNet.StaticFiles"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"1.0.0-rc1-final"</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
    </span><span class="str">"commands"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"web"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:60000"</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
    </span><span class="str">"frameworks"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"dnxcore50"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
    </span><span class="str">"fileServer"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"rootDirectory"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"c:\\users\\username\\Documents"</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثالثًا: اِنشِئ ملف باسم <code>Startup.cs</code> وأضف إليه الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_21" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Microsoft</span><span class="pun">.</span><span class="typ">AspNet</span><span class="pun">.</span><span class="typ">Builder</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Microsoft</span><span class="pun">.</span><span class="typ">AspNet</span><span class="pun">.</span><span class="typ">FileProviders</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Microsoft</span><span class="pun">.</span><span class="typ">AspNet</span><span class="pun">.</span><span class="typ">Hosting</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Microsoft</span><span class="pun">.</span><span class="typ">AspNet</span><span class="pun">.</span><span class="typ">StaticFiles</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Microsoft</span><span class="pun">.</span><span class="typ">Extensions</span><span class="pun">.</span><span class="typ">Configuration</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Startup</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Configure</span><span class="pun">(</span><span class="typ">IApplicationBuilder</span><span class="pln"> app</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var builder </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ConfigurationBuilder</span><span class="pun">();</span><span class="pln">
        builder</span><span class="pun">.</span><span class="typ">AddJsonFile</span><span class="pun">(</span><span class="str">"project.json"</span><span class="pun">);</span><span class="pln">

        var config </span><span class="pun">=</span><span class="pln"> builder</span><span class="pun">.</span><span class="typ">Build</span><span class="pun">();</span><span class="pln">
        var rootDirectory </span><span class="pun">=</span><span class="pln"> config</span><span class="pun">[</span><span class="str">"fileServer:rootDirectory"</span><span class="pun">];</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"File server root directory: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> rootDirectory</span><span class="pun">);</span><span class="pln">

        var fileProvider </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">PhysicalFileProvider</span><span class="pun">(</span><span class="pln">rootDirectory</span><span class="pun">);</span><span class="pln">

        var options </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StaticFileOptions</span><span class="pun">();</span><span class="pln">
        options</span><span class="pun">.</span><span class="typ">ServeUnknownFileTypes</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
        options</span><span class="pun">.</span><span class="typ">FileProvider</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> fileProvider</span><span class="pun">;</span><span class="pln">
        options</span><span class="pun">.</span><span class="typ">OnPrepareResponse</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> context </span><span class="pun">=&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            context</span><span class="pun">.</span><span class="typ">Context</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">.</span><span class="typ">ContentType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"application/octet-stream"</span><span class="pun">;</span><span class="pln">
            context</span><span class="pun">.</span><span class="typ">Context</span><span class="pun">.</span><span class="typ">Response</span><span class="pun">.</span><span class="typ">Headers</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">
                </span><span class="str">"Content-Disposition"</span><span class="pun">,</span><span class="pln">
                $</span><span class="str">"Attachment; filename=\"{context.File.Name}\""</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">

        app</span><span class="pun">.</span><span class="typ">UseStaticFiles</span><span class="pun">(</span><span class="pln">options</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ اِستخدَام التابع <code>UseStaticFiles</code> لتزويد الخادم بخاصية قراءة الملفات الساكنة من مجلد معين.
</p>

<p>
	رابعًا: اِفتَح سطر الأوامر (command prompt) في المجلد الذي قُمت لتوك بإنشائه، ونفذ الأوامر التالية:
</p>

<pre class="ipsCode">
dnvm use 1.0.0-rc1-final -r coreclr -p
dnu restore
</pre>

<p>
	تُنْفَّذ الأوامر بالأعلى مرة واحدة فقط.
</p>

<p>
	خامسًا: شَغِّل الخادم باستخدَام الأمر <code>dnx web</code>. كلمة web هنا هي مُجرد كلمة مُخصَّصة ضِمْن حَقْل الأوامر <code>commands</code> بالملف <code>project.json</code> وتُستخدَم اسمًا تعريفيًا لأمر مُخصَّص، وبالتالي ما يُنْفَّذ بالفعل هو قيمة هذا الحقل بالملف.
</p>

<pre class="ipsCode">
`Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:60000
</pre>

<p>
	والآن تستطيع إرسال طلبات (requests) إلى الخادم من خلال الرابط <a href="http://localhost:60000" ipsnoembed="false" rel="external nofollow">http://localhost:60000</a> وهو نفس الرابط (url) المُخصَّص بالأعلى.
</p>

<p>
	لاحظ أننا لغرض التبسيط قد افترضنا أن أسماء جميع الملفات ستكون بترميز ASCII، بالإضافة إلى أننا لم نُعالِج الأخطاء المُحتمَلة أثناء الولوج للملفات.
</p>

<h2>
	عميل HTTP
</h2>

<p>
	يَتوَفر الصنف <code>HttpClient</code> من خلال <a href="https://www.nuget.org/packages/Microsoft.Net.Http/" rel="external nofollow">حزمة مكتبات مايكروسوفت Microsoft HTTP Client Libraries</a>.
</p>

<h3>
	إرسال طلب GET باستخدام HttpClient.GetAsync
</h3>

<p>
	يُرسِل التابع <code>GetAsync</code> طلب <code>GET</code> إلى خَادِم (server) عن طريق رابط يُمرَّر إليه كمُعامِل، ويُعيد قيمة من النوع <code>Task&lt;HttpResponseMessage&gt;‎</code> تُمثِل رد الخادم (response). يُمكن قراءة الرد كـسِلسِلة نصية <code>string</code> باستخدام التابع <code>response.Content.ReadAsStringAsync</code>، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_23" style="">
<span class="pln">string requestUri </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://www.example.com"</span><span class="pun">;</span><span class="pln">
string responseData</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HttpClient</span><span class="pun">())</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pun">(</span><span class="pln">var response </span><span class="pun">=</span><span class="pln"> client</span><span class="pun">.</span><span class="typ">GetAsync</span><span class="pun">(</span><span class="pln">requestUri</span><span class="pun">).</span><span class="typ">Result</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        response</span><span class="pun">.</span><span class="typ">EnsureSuccessStatusCode</span><span class="pun">();</span><span class="pln">
        responseData </span><span class="pun">=</span><span class="pln"> response</span><span class="pun">.</span><span class="typ">Content</span><span class="pun">.</span><span class="typ">ReadAsStringAsync</span><span class="pun">().</span><span class="typ">Result</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إرسال طلب GET باستخدام HttpClient.GetStreamAsync
</h3>

<p>
	يُرسِل التابع <code>HttpClient.GetStreamAsync</code> طلب <code>GET</code> إلى خَادِم (server) عن طريق رابط يُمرَّر إليه كمُعامِل، ولكنه يُعيد مَتْن الرد (response body) في صورة مَجْرى (stream).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_25" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> async </span><span class="typ">Task</span><span class="pln"> </span><span class="typ">DownloadAsync</span><span class="pun">(</span><span class="pln">string fromUrl</span><span class="pun">,</span><span class="pln"> string toFile</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var fileStream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">OpenWrite</span><span class="pun">(</span><span class="pln">toFile</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var httpClient </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HttpClient</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Connecting..."</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var networkStream </span><span class="pun">=</span><span class="pln"> await httpClient</span><span class="pun">.</span><span class="typ">GetStreamAsync</span><span class="pun">(</span><span class="pln">fromUrl</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Downloading..."</span><span class="pun">);</span><span class="pln">
                await networkStream</span><span class="pun">.</span><span class="typ">CopyToAsync</span><span class="pun">(</span><span class="pln">fileStream</span><span class="pun">);</span><span class="pln">
                await fileStream</span><span class="pun">.</span><span class="typ">FlushAsync</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">   
</span><span class="pun">}</span></pre>

<p>
	يُمكن استدعاء الدالة المُعرَّفة بالأعلى كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_27" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Linq</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">Http</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Threading</span><span class="pun">.</span><span class="typ">Tasks</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HttpGet</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Run</span><span class="pun">(</span><span class="pln">args</span><span class="pun">).</span><span class="typ">Wait</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ex is </span><span class="typ">AggregateException</span><span class="pun">)</span><span class="pln">
                ex </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="typ">AggregateException</span><span class="pun">)</span><span class="pln">ex</span><span class="pun">)</span><span class="pln">
                        </span><span class="pun">.</span><span class="typ">Flatten</span><span class="pun">().</span><span class="typ">InnerExceptions</span><span class="pun">.</span><span class="typ">First</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Error: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln">
                              </span><span class="pun">(</span><span class="pln">ex</span><span class="pun">.</span><span class="typ">InnerException</span><span class="pun">?.</span><span class="typ">Message</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> ex</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> async </span><span class="typ">Task</span><span class="pln"> </span><span class="typ">Run</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Basic HTTP downloader"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Usage: httpget &lt;url&gt;[&lt;:port&gt;] &lt;file&gt;"</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        await </span><span class="typ">DownloadAsync</span><span class="pun">(</span><span class="pln">fromUrl</span><span class="pun">:</span><span class="pln"> args</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> toFile</span><span class="pun">:</span><span class="pln"> args</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Done!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إرسال طلب POST باستخدام HttpClient.SendAsync
</h3>

<p>
	يُهيَّّئ الطلب في صورة كائن من النوع <code>HttpRequestMessage</code>، فمثلًا تُسْنَد قيمة الرابط للخاصية <code>RequestUri</code> بينما تُسنَد قيمة المَتْن (request body) للخاصية <code>Content</code>.
</p>

<p>
	يُرسِل التابع <code>SendAsync</code> طلب <code>POST</code> إلى الخَادِم مع قيمة الطلب المُهيَّئ، ويُعيد قيمة من النوع <code>Task&lt;HttpResponseMessage&gt;‎</code> تُمثِل رد الخادم (response)، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_29" style="">
<span class="pln">string requestUri </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://www.example.com"</span><span class="pun">;</span><span class="pln">
string requestBodyString </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Request body string."</span><span class="pun">;</span><span class="pln">
string contentType </span><span class="pun">=</span><span class="pln"> </span><span class="str">"text/plain"</span><span class="pun">;</span><span class="pln">
string requestMethod </span><span class="pun">=</span><span class="pln"> </span><span class="str">"POST"</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HttpClient</span><span class="pun">())</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var request </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HttpRequestMessage</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">RequestUri</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> requestUri</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">Method</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> requestMethod</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    byte</span><span class="pun">[]</span><span class="pln"> requestBodyBytes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">UTF8</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">requestBodyString</span><span class="pun">);</span><span class="pln">
    request</span><span class="pun">.</span><span class="typ">Content</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ByteArrayContent</span><span class="pun">(</span><span class="pln">requestBodyBytes</span><span class="pun">);</span><span class="pln">
    request</span><span class="pun">.</span><span class="typ">Content</span><span class="pun">.</span><span class="typ">Headers</span><span class="pun">.</span><span class="typ">ContentType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MediaTypeHeaderValue</span><span class="pun">(</span><span class="pln">contentType</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">HttpResponseMessage</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> client</span><span class="pun">.</span><span class="typ">SendAsync</span><span class="pun">(</span><span class="pln">request</span><span class="pun">).</span><span class="typ">Result</span><span class="pun">;</span><span class="pln">
    result</span><span class="pun">.</span><span class="typ">EnsureSuccessStatusCode</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إرسال طلب GET باستخدام HttpWebRequest.GetResponse
</h3>

<p>
	يُهيِّئ التابع <code>WebRequest.Create</code> طلب <code>GET</code> إلى خادم (server) بمُعامِل الرابط المُمرَّر إليه، ثم يتم الارسال الفعلي بواسطة التابع <code>GetResponse</code> وتُعاد قيمة من النوع <code>WebResponse</code> تُمثِل رد الخادم. في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_31" style="">
<span class="pln">string requestUri </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://www.example.com"</span><span class="pun">;</span><span class="pln">
string responseData</span><span class="pun">;</span><span class="pln">

</span><span class="typ">HttpWebRequest</span><span class="pln"> request </span><span class="pun">=(</span><span class="typ">HttpWebRequest</span><span class="pun">)</span><span class="typ">WebRequest</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">(</span><span class="pln">parameters</span><span class="pun">.</span><span class="typ">Uri</span><span class="pun">);</span><span class="pln">
</span><span class="typ">WebResponse</span><span class="pln"> response </span><span class="pun">=</span><span class="pln"> request</span><span class="pun">.</span><span class="typ">GetResponse</span><span class="pun">();</span></pre>

<p>
	يُمكن تَحويل رد الخَادِم إلى سِلسِلة نصية كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_33" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamReader</span><span class="pln"> responseReader </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamReader</span><span class="pun">(</span><span class="pln">response</span><span class="pun">.</span><span class="typ">GetResponseStream</span><span class="pun">()))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    responseData </span><span class="pun">=</span><span class="pln"> responseReader</span><span class="pun">.</span><span class="typ">ReadToEnd</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إرسال طلب POST باستخدام HttpWebRequest.GetResponse
</h3>

<p>
	يُهيِّئ التابع <code>WebRequest.Create</code> طلب <code>POST</code> إلى خادم (server) بمُعامِل الرابط المُمرر إليه. قد تحتاج إلى تهيئة مَتْن الطلب (request body) أيضًا. للقيام بذلك، استخدم التابع <code>GetRequestStream</code> لاستعادة مَتْن الطلب بصورة مَجْرى (stream) يُكتَّب عليه المُحتوَى المطلوب.
</p>

<p>
	بعد انتهاء التهيئة، يتم الارسال الفعلي بواسطة التابع <code>GetResponse</code> وتُعاد قيمة من النوع <code>WebResponse</code> تُمثِل رد الخادم. في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_35" style="">
<span class="pln">string requestUri </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://www.example.com"</span><span class="pun">;</span><span class="pln">
string requestBodyString </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Request body string."</span><span class="pun">;</span><span class="pln">
string contentType </span><span class="pun">=</span><span class="pln"> </span><span class="str">"text/plain"</span><span class="pun">;</span><span class="pln">
string requestMethod </span><span class="pun">=</span><span class="pln"> </span><span class="str">"POST"</span><span class="pun">;</span><span class="pln">

</span><span class="typ">HttpWebRequest</span><span class="pln"> request </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">HttpWebRequest</span><span class="pun">)</span><span class="typ">WebRequest</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">(</span><span class="pln">requestUri</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Method</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> requestMethod</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">ContentType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> contentType</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

byte</span><span class="pun">[]</span><span class="pln"> bytes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">UTF8</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">requestBodyString</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Stream</span><span class="pln"> stream </span><span class="pun">=</span><span class="pln"> request</span><span class="pun">.</span><span class="typ">GetRequestStream</span><span class="pun">();</span><span class="pln">
stream</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">bytes</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> bytes</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span><span class="pln">
stream</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span><span class="pln">

</span><span class="typ">HttpWebResponse</span><span class="pln"> response </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">HttpWebResponse</span><span class="pun">)</span><span class="pln">request</span><span class="pun">.</span><span class="typ">GetResponse</span><span class="pun">();</span></pre>

<h3>
	رفع ملفات إلى خادم باستخدام HttpWebRequest.GetResponseAsync
</h3>

<p>
	تُرفَّع الملفات إلى الخوادم من خلال إرسال طلب POST إلى الخادم مع إرفاق مُحتوَى الملف ضِمْن مَتْن الطلب.
</p>

<p>
	يُهيِّئ التابع <code>WebRequest.CreateHttp</code> طلب (request) إلى خادم (server) بمُعامِل الرابط المُمرَّر إليه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_37" style="">
<span class="pln">var request </span><span class="pun">=</span><span class="pln"> </span><span class="typ">WebRequest</span><span class="pun">.</span><span class="typ">CreateHttp</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span></pre>

<p>
	قد تحتاج إلى تهيئة إضافية للطلب مثل إضافة مَتْن إليه (request body). للقيام بذلك، اِستخدِم التابع <code>GetRequestStream</code> لاستعادة مَتْن الطلب بصورة مَجْرى (stream). تستطيع الكتابة على المَجْرى مباشرة أو تَضْمِينه داخل كائن من النوع <code>StreamWriter</code> ثم تَكتِب عليه المُحتوَى المطلوب.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_39" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var requestStream </span><span class="pun">=</span><span class="pln"> request</span><span class="pun">.</span><span class="typ">GetRequestStream</span><span class="pun">())</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var writer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">requestStream</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    await writer</span><span class="pun">.</span><span class="typ">WriteAsync</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نَحتَاج لرَفع ملف إلى الخادم، مما يعني كتابة مُحتوَيات هذا الملف على مَجْرى مَتْن الطلب. يُفتَح الملف أولًا في صورة مَجْرى ثم تُنقَل محتوياته لمَجْرى الطلب، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_41" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var fileStream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">OpenRead</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">))</span><span class="pln">
    await fileStream</span><span class="pun">.</span><span class="typ">CopyToAsync</span><span class="pun">(</span><span class="pln">requestStream</span><span class="pun">);</span></pre>

<p>
	بعد انتهاء التهيئة، يتم الارسال الفعلي للطلب بواسطة التابع <code>GetResponseAsync</code> وتُعاد قيمة من النوع <code>Task&lt;WebResponse&gt;‎</code> تُمثِل رد الخادم، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_43" style="">
<span class="pln">var response </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">HttpWebResponse</span><span class="pun">)</span><span class="pln"> await request</span><span class="pun">.</span><span class="typ">GetResponseAsync</span><span class="pun">();</span></pre>

<p>
	تستعرض الشيفرة التالية المثال بالكامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_45" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Collections</span><span class="pun">.</span><span class="typ">Generic</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Threading</span><span class="pun">.</span><span class="typ">Tasks</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> async </span><span class="typ">Task</span><span class="str">&lt;string&gt;</span><span class="pln"> </span><span class="typ">UploadFile</span><span class="pun">(</span><span class="pln">string url</span><span class="pun">,</span><span class="pln"> 
                                     string filename</span><span class="pun">,</span><span class="pln">
                                     </span><span class="typ">Dictionary</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> object</span><span class="pun">&gt;</span><span class="pln"> postData</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">

    var request </span><span class="pun">=</span><span class="pln"> </span><span class="typ">WebRequest</span><span class="pun">.</span><span class="typ">CreateHttp</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span><span class="pln">
    var boundary </span><span class="pun">=</span><span class="pln"> $</span><span class="str">"{Guid.NewGuid():N}"</span><span class="pun">;</span><span class="pln"> 

    request</span><span class="pun">.</span><span class="typ">ContentType</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $</span><span class="str">"multipart/form-data; {nameof(boundary)}={boundary}"</span><span class="pun">;</span><span class="pln">
    request</span><span class="pun">.</span><span class="typ">Method</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"POST"</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var requestStream </span><span class="pun">=</span><span class="pln"> request</span><span class="pun">.</span><span class="typ">GetRequestStream</span><span class="pun">())</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var writer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">requestStream</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        foreach </span><span class="pun">(</span><span class="pln">var data in postData</span><span class="pun">)</span><span class="pln">
            await writer</span><span class="pun">.</span><span class="typ">WriteAsync</span><span class="pun">(</span><span class="pln"> 
            $</span><span class="str">"\r\n--{boundary}\r\nContent-Disposition: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln">
            $</span><span class="str">"form-data; name=\"{data.Key}\"\r\n\r\n{data.Value}"</span><span class="pun">);</span><span class="pln">

        await writer</span><span class="pun">.</span><span class="typ">WriteAsync</span><span class="pun">(</span><span class="pln"> </span><span class="com">// file header</span><span class="pln">
            $</span><span class="str">"\r\n--{boundary}\r\nContent-Disposition: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln">
            $</span><span class="str">"form-data; name=\"File\"; filename=\"{Path.GetFileName(filename)}\"\r\n"</span><span class="pln"> </span><span class="pun">+</span><span class="pln">
            </span><span class="str">"Content-Type: application/octet-stream\r\n\r\n"</span><span class="pun">);</span><span class="pln">

        await writer</span><span class="pun">.</span><span class="typ">FlushAsync</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var fileStream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">OpenRead</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">))</span><span class="pln">
            await fileStream</span><span class="pun">.</span><span class="typ">CopyToAsync</span><span class="pun">(</span><span class="pln">requestStream</span><span class="pun">);</span><span class="pln">

        await writer</span><span class="pun">.</span><span class="typ">WriteAsync</span><span class="pun">(</span><span class="pln">$</span><span class="str">"\r\n--{boundary}--\r\n"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var response </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">HttpWebResponse</span><span class="pun">)</span><span class="pln"> await request</span><span class="pun">.</span><span class="typ">GetResponseAsync</span><span class="pun">())</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var responseStream </span><span class="pun">=</span><span class="pln"> response</span><span class="pun">.</span><span class="typ">GetResponseStream</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">responseStream </span><span class="pun">==</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> string</span><span class="pun">.</span><span class="typ">Empty</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var reader </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamReader</span><span class="pun">(</span><span class="pln">responseStream</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> await reader</span><span class="pun">.</span><span class="typ">ReadToEndAsync</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إرسال طلب GET باستخدام WebClient.DownloadString
</h3>

<p>
	يُرسِل التابع <code>DownloadString</code> طلب <code>GET</code> إلى خادم (server) عن طريق مُعامِل الرابط المُمرر إليه، ويُعيد قيمة من النوع <code>string</code> تُمثِل رد الخادم.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_47" style="">
<span class="pln">string requestUri </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://www.example.com"</span><span class="pun">;</span><span class="pln">
string responseData</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WebClient</span><span class="pun">())</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    responseData </span><span class="pun">=</span><span class="pln"> client</span><span class="pun">.</span><span class="typ">DownloadString</span><span class="pun">(</span><span class="pln">requestUri</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إرسال طلب POST باستخدام WebClient.UploadData
</h3>

<p>
	يُرسِل التابع <code>UploadData</code> طلب <code>POST</code> إلى خادم (server) مع مَتْن الطلب المُمرر له، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_49" style="">
<span class="pln">string requestUri </span><span class="pun">=</span><span class="pln"> </span><span class="str">"http://www.example.com"</span><span class="pun">;</span><span class="pln">
string requestBodyString </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Request body string."</span><span class="pun">;</span><span class="pln">
string contentType </span><span class="pun">=</span><span class="pln"> </span><span class="str">"text/plain"</span><span class="pun">;</span><span class="pln">
string requestMethod </span><span class="pun">=</span><span class="pln"> </span><span class="str">"POST"</span><span class="pun">;</span><span class="pln">

byte</span><span class="pun">[]</span><span class="pln"> responseBody</span><span class="pun">;</span><span class="pln">
byte</span><span class="pun">[]</span><span class="pln"> requestBodyBytes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">UTF8</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">requestBodyString</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WebClient</span><span class="pun">())</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    client</span><span class="pun">.</span><span class="typ">Headers</span><span class="pun">[</span><span class="typ">HttpRequestHeader</span><span class="pun">.</span><span class="typ">ContentType</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> contentType</span><span class="pun">;</span><span class="pln">
    responseBody </span><span class="pun">=</span><span class="pln"> client</span><span class="pun">.</span><span class="typ">UploadData</span><span class="pun">(</span><span class="pln">requestUri</span><span class="pun">,</span><span class="pln"> requestMethod</span><span class="pun">,</span><span class="pln"> requestBodyBytes</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	عميل SMTP لإرسال بريد إلكتروني
</h2>

<p>
	يُمكِنك بسهولة إنشاء كائن من النوع <code>MailMessage</code> بحيث يَحمِل معلومات البريد الإلكتروني المَطلوب إرساله، ثم مَرِّره إلى كائن من النوع <code>SmtpClient</code> حتى يقوم بالإرسال الفعلي.
</p>

<p>
	يَحتوِي النوع <code>MailMessage</code> على الخاصيات:
</p>

<ul>
<li>
		To
	</li>
	<li>
		From
	</li>
	<li>
		ReplyToList
	</li>
	<li>
		CC
	</li>
	<li>
		Bcc
	</li>
	<li>
		Subject
	</li>
	<li>
		Body
	</li>
	<li>
		IsBodyHtml
	</li>
	<li>
		Attachments
	</li>
	<li>
		Priority والتي يُمكن ضَبْط قيمها كأيّ بريد الكتروني عادي.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_51" style="">
<span class="kwd">using</span><span class="pun">(</span><span class="typ">MailMessage</span><span class="pln"> </span><span class="typ">MyMail</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MailMessage</span><span class="pun">())</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">From</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MailAddress</span><span class="pun">(</span><span class="pln">mailfrom</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">To</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">mailto</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">ReplyToList</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">replyto</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="pln">CC</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">mailcc</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Bcc</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">mailbcc</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Subject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> subject</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">IsBodyHtml</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Body</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> body</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Priority</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MailPriority</span><span class="pun">.</span><span class="typ">Normal</span><span class="pun">;</span><span class="pln">

    </span><span class="com">//</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المقابل، يَحتوِي النوع <code>SmtpClient</code> على الخاصيات <code>Host</code> و <code>Port</code> و <code>Credentials</code> لتخصيص بيانات خَادِم الـ SMTP المُستخدَم لإرسال البريد الإلكتروني.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_53" style="">
<span class="typ">SmtpClient</span><span class="pln"> smtpMailObj </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SmtpClient</span><span class="pun">();</span><span class="pln">
smtpMailObj</span><span class="pun">.</span><span class="typ">Host</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"your host"</span><span class="pun">;</span><span class="pln">
smtpMailObj</span><span class="pun">.</span><span class="typ">Port</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">25</span><span class="pun">;</span><span class="pln">
smtpMailObj</span><span class="pun">.</span><span class="typ">Credentials</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">NetworkCredential</span><span class="pun">(</span><span class="str">"uid"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"pwd"</span><span class="pun">);</span></pre>

<p>
	الشيفرة بالكامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_55" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> clsMail
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">SendMail</span><span class="pun">(</span><span class="pln">string mailfrom</span><span class="pun">,</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;string&gt;</span><span class="pln">replytos</span><span class="pun">,</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;string&gt;</span><span class="pln"> mailtos</span><span class="pun">,</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;string&gt;</span><span class="pln"> mailccs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;string&gt;</span><span class="pln"> mailbccs</span><span class="pun">,</span><span class="pln"> string body</span><span class="pun">,</span><span class="pln"> string subject</span><span class="pun">,</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;string&gt;</span><span class="pln"> </span><span class="typ">Attachment</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pun">(</span><span class="typ">MailMessage</span><span class="pln"> </span><span class="typ">MyMail</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MailMessage</span><span class="pun">())</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">From</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MailAddress</span><span class="pun">(</span><span class="pln">mailfrom</span><span class="pun">);</span><span class="pln">

                foreach </span><span class="pun">(</span><span class="pln">string mailto in mailtos</span><span class="pun">)</span><span class="pln">
                    </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">To</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">mailto</span><span class="pun">);</span><span class="pln">

                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">replytos </span><span class="pun">!=</span><span class="pln"> null </span><span class="pun">&amp;&amp;</span><span class="pln"> replytos</span><span class="pun">.</span><span class="typ">Any</span><span class="pun">())</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    foreach </span><span class="pun">(</span><span class="pln">string replyto in replytos</span><span class="pun">)</span><span class="pln">
                        </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">ReplyToList</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">replyto</span><span class="pun">);</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">mailccs </span><span class="pun">!=</span><span class="pln"> null </span><span class="pun">&amp;&amp;</span><span class="pln"> mailccs</span><span class="pun">.</span><span class="typ">Any</span><span class="pun">())</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    foreach </span><span class="pun">(</span><span class="pln">string mailcc in mailccs</span><span class="pun">)</span><span class="pln">
                        </span><span class="typ">MyMail</span><span class="pun">.</span><span class="pln">CC</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">mailcc</span><span class="pun">);</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">mailbccs </span><span class="pun">!=</span><span class="pln"> null </span><span class="pun">&amp;&amp;</span><span class="pln"> mailbccs</span><span class="pun">.</span><span class="typ">Any</span><span class="pun">())</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    foreach </span><span class="pun">(</span><span class="pln">string mailbcc in mailbccs</span><span class="pun">)</span><span class="pln">
                        </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Bcc</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">mailbcc</span><span class="pun">);</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Subject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> subject</span><span class="pun">;</span><span class="pln">
                </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">IsBodyHtml</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
                </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Body</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> body</span><span class="pun">;</span><span class="pln">
                </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Priority</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MailPriority</span><span class="pun">.</span><span class="typ">Normal</span><span class="pun">;</span><span class="pln">

                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Attachment</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> null </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="typ">Attachment</span><span class="pun">.</span><span class="typ">Any</span><span class="pun">())</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">Mail</span><span class="pun">.</span><span class="typ">Attachment</span><span class="pln"> attachment</span><span class="pun">;</span><span class="pln">
                    foreach </span><span class="pun">(</span><span class="pln">var item in </span><span class="typ">Attachment</span><span class="pun">)</span><span class="pln">
                    </span><span class="pun">{</span><span class="pln">
                        attachment </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">Mail</span><span class="pun">.</span><span class="typ">Attachment</span><span class="pun">(</span><span class="pln">item</span><span class="pun">);</span><span class="pln">
                        </span><span class="typ">MyMail</span><span class="pun">.</span><span class="typ">Attachments</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">attachment</span><span class="pun">);</span><span class="pln">
                    </span><span class="pun">}</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                </span><span class="typ">SmtpClient</span><span class="pln"> smtpMailObj </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SmtpClient</span><span class="pun">();</span><span class="pln">
                smtpMailObj</span><span class="pun">.</span><span class="typ">Host</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"your host"</span><span class="pun">;</span><span class="pln">
                smtpMailObj</span><span class="pun">.</span><span class="typ">Port</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">25</span><span class="pun">;</span><span class="pln">
                smtpMailObj</span><span class="pun">.</span><span class="typ">Credentials</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">NetworkCredential</span><span class="pun">(</span><span class="str">"uid"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"pwd"</span><span class="pun">);</span><span class="pln">

                smtpMailObj</span><span class="pun">.</span><span class="typ">Send</span><span class="pun">(</span><span class="typ">MyMail</span><span class="pun">);</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُدعم النوع <code>MailMessage</code> إضافة المُرفَقات من خلال الخاصية <code>Attachments</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_57" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">Mail</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pun">(</span><span class="typ">MailMessage</span><span class="pln"> myMail </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MailMessage</span><span class="pun">())</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Attachment</span><span class="pln"> attachment </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Attachment</span><span class="pun">(</span><span class="pln">path</span><span class="pun">);</span><span class="pln">
    myMail</span><span class="pun">.</span><span class="typ">Attachments</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">attachment</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	عميل UDP لمزامنة التوقيت باستخدام خادم SNTP
</h2>

<p>
	يُمكِن لعميل إرسال طلبات لخادم SNTP لمُزامنة التوقيت مع ذلك الخادم. اطلع على <a href="http://tools.ietf.org/html/rfc2030" rel="external nofollow">RFC 2030</a> للمزيد من المعلومات عن بروتوكول <code>SNTP</code>.
</p>

<p>
	تجهيز طلب SNTP كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_59" style="">
<span class="pln">var sntpRequest </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">48</span><span class="pun">];</span><span class="pln">
sntpRequest</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x23</span><span class="pun">;</span><span class="pln"> </span><span class="com">//LI=0 (no warning), VN=4, Mode=3 (client)</span></pre>

<p>
	إرسال الطلب من خلال الصنف <code>UDPClient</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_61" style="">
<span class="pln">var udpClient </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">UdpClient</span><span class="pun">();</span><span class="pln">
udpClient</span><span class="pun">.</span><span class="typ">Client</span><span class="pun">.</span><span class="typ">ReceiveTimeout</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">;</span><span class="pln">
udpClient</span><span class="pun">.</span><span class="typ">Send</span><span class="pun">(</span><span class="pln">
    dgram</span><span class="pun">:</span><span class="pln"> sntpRequest</span><span class="pun">,</span><span class="pln">
    bytes</span><span class="pun">:</span><span class="pln"> sntpRequest</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">,</span><span class="pln">
    hostname</span><span class="pun">:</span><span class="pln"> args</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
    port</span><span class="pun">:</span><span class="pln"> </span><span class="typ">SntpPort</span><span class="pun">);</span></pre>

<p>
	مُزامنة التوقيت:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_63" style="">
<span class="pln">var date </span><span class="pun">=</span><span class="pln"> </span><span class="typ">BaseDate</span><span class="pun">.</span><span class="typ">AddSeconds</span><span class="pun">(</span><span class="pln">numberOfSeconds</span><span class="pun">).</span><span class="typ">AddHours</span><span class="pun">(</span><span class="pln">localTimeZoneInHours</span><span class="pun">);</span></pre>

<p>
	الشيفرة بالكامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_65" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Globalization</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Linq</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">Sockets</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SntpClient</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">SntpPort</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pln"> </span><span class="typ">BaseDate</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">(</span><span class="lit">1900</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">

        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">args</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Simple SNTP client"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Usage: sntpclient &lt;sntp server url&gt; [&lt;local timezone&gt;]"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"&lt;local timezone&gt;: a number between -12 and 12 as hours from UTC"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"(append .5 for an extra half an hour)"</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">double</span><span class="pln"> localTimeZoneInHours </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">args</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
            localTimeZoneInHours </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="pln">args</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="typ">CultureInfo</span><span class="pun">.</span><span class="typ">InvariantCulture</span><span class="pun">);</span><span class="pln">

        var udpClient </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">UdpClient</span><span class="pun">();</span><span class="pln">
        udpClient</span><span class="pun">.</span><span class="typ">Client</span><span class="pun">.</span><span class="typ">ReceiveTimeout</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">;</span><span class="pln">

        var sntpRequest </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">48</span><span class="pun">];</span><span class="pln">
        sntpRequest</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x23</span><span class="pun">;</span><span class="pln"> </span><span class="com">//LI=0 (no warning), VN=4, Mode=3 (client)</span><span class="pln">
        udpClient</span><span class="pun">.</span><span class="typ">Send</span><span class="pun">(</span><span class="pln">
            dgram</span><span class="pun">:</span><span class="pln"> sntpRequest</span><span class="pun">,</span><span class="pln">
            bytes</span><span class="pun">:</span><span class="pln"> sntpRequest</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">,</span><span class="pln">
            hostname</span><span class="pun">:</span><span class="pln"> args</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
            port</span><span class="pun">:</span><span class="pln"> </span><span class="typ">SntpPort</span><span class="pun">);</span><span class="pln">

        byte</span><span class="pun">[]</span><span class="pln"> sntpResponse</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">IPEndPoint</span><span class="pln"> remoteEndpoint </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
            sntpResponse </span><span class="pun">=</span><span class="pln"> udpClient</span><span class="pun">.</span><span class="typ">Receive</span><span class="pun">(</span><span class="pln">ref remoteEndpoint</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">SocketException</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"*** No response received from the server"</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="typ">uint</span><span class="pln"> numberOfSeconds</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">IsLittleEndian</span><span class="pun">)</span><span class="pln">
            numberOfSeconds </span><span class="pun">=</span><span class="pln"> </span><span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">
            sntpResponse</span><span class="pun">.</span><span class="typ">Skip</span><span class="pun">(</span><span class="lit">40</span><span class="pun">).</span><span class="typ">Take</span><span class="pun">(</span><span class="lit">4</span><span class="pun">).</span><span class="typ">Reverse</span><span class="pun">().</span><span class="typ">ToArray</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
            numberOfSeconds </span><span class="pun">=</span><span class="pln"> </span><span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToUInt32</span><span class="pun">(</span><span class="pln">sntpResponse</span><span class="pun">,</span><span class="pln"> </span><span class="lit">40</span><span class="pun">);</span><span class="pln">

        var date </span><span class="pun">=</span><span class="pln"> </span><span class="typ">BaseDate</span><span class="pun">.</span><span class="typ">AddSeconds</span><span class="pun">(</span><span class="pln">numberOfSeconds</span><span class="pun">).</span><span class="typ">AddHours</span><span class="pun">(</span><span class="pln">localTimeZoneInHours</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">
            $</span><span class="str">"Current date in server: {date:yyyy-MM-dd HH:mm:ss} UTC{localTimeZoneInHours:+0.#;-0.#;.}"</span><span class="pun">);</span><span class="pln">

    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	خادم وعميل TCP لتنشئة برنامج دردشة
</h2>

<p>
	باستخدام الأنواع <code>TcpListener</code> و <code>TcpClient</code> و <code>NetworkStream</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6073_67" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Net</span><span class="pun">.</span><span class="typ">Sockets</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TcpChat</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">args</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Basic TCP chat"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Usage:"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"tcpchat server &lt;port&gt;"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"tcpchat client &lt;url&gt; &lt;port&gt;"</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Run</span><span class="pun">(</span><span class="pln">args</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">IOException</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Connection lost"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">SocketException</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Can't connect: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> ex</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Run</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">TcpClient</span><span class="pln"> client</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">NetworkStream</span><span class="pln"> stream</span><span class="pun">;</span><span class="pln">
        byte</span><span class="pun">[]</span><span class="pln"> buffer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">256</span><span class="pun">];</span><span class="pln">
        var encoding </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">ASCII</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">args</span><span class="pun">[</span><span class="lit">0</span><span class="pun">].</span><span class="typ">StartsWith</span><span class="pun">(</span><span class="str">"s"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">StringComparison</span><span class="pun">.</span><span class="typ">InvariantCultureIgnoreCase</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            var port </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="pln">args</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">
            var listener </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TcpListener</span><span class="pun">(</span><span class="typ">IPAddress</span><span class="pun">.</span><span class="typ">Any</span><span class="pun">,</span><span class="pln"> port</span><span class="pun">);</span><span class="pln">
            listener</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Waiting for a connection..."</span><span class="pun">);</span><span class="pln">
            client </span><span class="pun">=</span><span class="pln"> listener</span><span class="pun">.</span><span class="typ">AcceptTcpClient</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            var hostName </span><span class="pun">=</span><span class="pln"> args</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">
            var port </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="pln">args</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]);</span><span class="pln">
            client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TcpClient</span><span class="pun">();</span><span class="pln">
            client</span><span class="pun">.</span><span class="typ">Connect</span><span class="pun">(</span><span class="pln">hostName</span><span class="pun">,</span><span class="pln"> port</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        stream </span><span class="pun">=</span><span class="pln"> client</span><span class="pun">.</span><span class="typ">GetStream</span><span class="pun">();</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"--- Connected. Start typing! (exit with Ctrl-C)"</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pun">(</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">KeyAvailable</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                var lineToSend </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span><span class="pln">
                var bytesToSend </span><span class="pun">=</span><span class="pln"> encoding</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">lineToSend </span><span class="pun">+</span><span class="pln"> </span><span class="str">"\r\n"</span><span class="pun">);</span><span class="pln">
                stream</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">bytesToSend</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> bytesToSend</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span><span class="pln">
                stream</span><span class="pun">.</span><span class="typ">Flush</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">stream</span><span class="pun">.</span><span class="typ">DataAvailable</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                var receivedBytesCount </span><span class="pun">=</span><span class="pln"> stream</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> buffer</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span><span class="pln">
                var receivedString </span><span class="pun">=</span><span class="pln"> encoding</span><span class="pun">.</span><span class="typ">GetString</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> receivedBytesCount</span><span class="pun">);</span><span class="pln">
                </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">receivedString</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصول:
</p>

<ul>
<li>
		HTTP servers
	</li>
	<li>
		HTTP clients
	</li>
	<li>
		Upload file and POST data to webserver
	</li>
	<li>
		System.Net.Mail
	</li>
	<li>
		Networking
	</li>
</ul>
<p>
	من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">999</guid><pubDate>Thu, 17 Sep 2020 10:18:01 +0000</pubDate></item><item><title>&#x644;&#x645;&#x62D;&#x629; &#x639;&#x646; &#x628;&#x64A;&#x626;&#x629; &#x62A;&#x637;&#x648;&#x64A;&#x631; NET Core.</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D9%84%D9%85%D8%AD%D8%A9-%D8%B9%D9%86-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-net-core-r998/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/20.png.19284a9effedc7e7bdfe3a5821dcd502.png" /></p>

<p>
	تُعدّ ‎.NET Core بيئة تطوير مُتَعدِّدة الأغراض، مُصانة بواسطة مايكروسوفت <code>Microsoft</code> ومجتمع الـ ‎.NET على GitHub. تتميز بكْونها مُتَعدِّدة المنصات (cross-platform) حيث تُدعِّم أنظمة التشغيل: ويندوز Windows وماك macOS ولينكس Linux. ويُمكِن اِستخدَامها بسياقات مُتَعدِّدة: على الأجهزة أو على السحاب (cloud) أو على الأجهزة المُدْمَجة (embedded) أو بإنترنت الأشياء (IoT).
</p>

<p>
	عندما تُفكِر ببيئة التطوير ‎.NET Core، فينبغي لمُصطلحات مثل سهولة النشر (flexible deployment) وتَعدُّد المنصات (cross-platform) وأدوات سطر الأوامر والمصدر المفتوح (open source) أن تَكون أول ما يطرأ بذهنك. على الرغم من كَوْنها مفتوحة المصدر، تُدعمها مايكروسوفت بشكل فعال.
</p>

<h2>
	الاختيار ما بين ‎.NET Framework و ‎.NET Core
</h2>

<p>
	تُعرِّف <code>‎.NET Standard</code> مُواصَفَات واجهة تطوير التطبيقات (‎.NET APIs) والتي تُمثِل مجموعة من المواصفات الاصطلاحية (contracts) تُصرَّف شيفرتك وفقًا لها. يَتوفَّر أكثر من مُنفِّذ لهذه المواصفات منها بيئتي العمل <code>‎.NET Framework</code> و <code>‎.NET Core</code>. يعني ذلك أنهما يشتركان في العديد من المُكوِنات ولكن توجد أيضًا بعض الاختلافات الجوهرية والتي يُساعدك الإطلاع عليها على الاختيار بينهما.
</p>

<h2>
	اختيار بيئة عمل ‎.NET Core
</h2>

<p>
	يُفضَّل استخدام بيئة عمل <code>‎.NET Core</code> في الحالات التالية:
</p>

<ul>
<li>
		الحاجة لتشغيل تطبيقك على منصات متعددة مثل ويندوز ولينكس وماك. تُدعِّم بيئة عمل <code>‎.NET Core</code> أيضًا إمكانية التطوير على الأنظمة المذكورة سلفًا.
	</li>
	<li>
		استهداف الخدمات المُصغرة (microservices).
	</li>
	<li>
		على الرغم من إمكانية استخدام بيئة عمل <code>‎.NET Framework</code> داخل حاويات ويندوز (Windows containers)، تُعدّ <code>‎.NET Core</code> أكثر مثالية للحاويات (containers) لما تتميز به من صغر الحجم وخفة الوزن. بالإضافة إلى كونها متعددة المنصات مما يُمكِنك من نشر تطبيقك على حاويات <code>Docker</code> بنظام لينكس على سبيل المثال.
	</li>
	<li>
		تُعدّ <code>‎.NET Core</code> خيارك الأفضل إذا كنت في حاجة إلى بناء أنظمة عالية المستوى قابلة للتوسع (scalable)، .
	</li>
</ul>
<h3>
	اختيار بيئة عمل ‎.NET Framework
</h3>

<p>
	على الرغم من أن بيئة عمل <code>‎.NET Core</code> تُوفِّر الكثير من المميزات خاصة للتطبيقات الجديدة، مع ذلك تَظل بيئة عمل <code>‎.NET Framework</code> الخيار الطبيعي في كثير من الحالات. مثلًا:
</p>

<ul>
<li>
		<p>
			إذا كان تطبيقك يعمل بالفعل على بيئة عمل <code>‎.NET Framework</code>، فأنت عادة لست في حاجة إلى تحويله.
		</p>
	</li>
	<li>
		<p>
			على الرغم من توجه المكتبات السريع لتبَنّى مواصفات <code>‎.NET Standard</code> والذي سيؤدي إلى توافق المكتبة مع جميع المُنفِّذين (implementations)، فقد يَستخدِم تطبيقك مكتبات <code>‎.NET</code> من طرف ثالث (third-party) أو حزم <code>NuGet</code> غير مُتاحة ببيئة عمل <code>‎.NET Core</code>. يُمكنك في هذه الحالات استخدام بيئة عمل <code>‎.NET Framework</code>.
		</p>
	</li>
	<li>
		<p>
			اِستخدَام تطبيقك لبعض تقنيات <code>‎.NET</code> غير المُتوفِّرة ببيئة عمل <code>‎.NET Core</code>.
		</p>
	</li>
	<li>
		<p>
			اِستخدَام تطبيقك لمنصة (platform) غير مُدعَّمة ببيئة عمل <code>‎.NET Core</code>.
		</p>
	</li>
</ul>
<h2>
	التحويل من ‎.NET Framework إلى ‎.NET Core
</h2>

<p>
	عملية تحويل الشيفرة المُطورة أساسًا لاستهداف بيئة عمل <code>‎.NET Framework</code> بحيث تُصبح متوافقة مع بيئة عمل <code>‎.NET Core</code> هي عملية بسيطة نسبيًا بغالبية المشروعات خاصة إذا كان نموذج المشروع (app model) متوفرًا بكلتا البيئتين كالمكتبات (libraries) وتطبيقات الطرفية (Console Applications)، أما المشروعات التي تتطلب إنشاء نموذج مشروع (app model) جديد كالانتقال من <code>ASP.NET</code> إلى <code>ASP.NET Core</code> فإن العملية قد تحتاج إلى مزيد من العمل ولكنها بالنهاية تَتَبع نمطًا ثابتًا.
</p>

<h3>
	تحويل حل (solution)
</h3>

<p>
	إذا كنت تعمل على حل (solution) به أكثر من مشروع، فقد تبدو العملية معقدة. لذلك فمن الأفضل أن تُحوِّل المشروعات تحويلًا تصاعديًا من أسفل لأعلى، بمعنى أن تبدأ أولًا بالمشروعات التي لا تَعتمِد على مشروعات اخرى، ثم تنتقل إلى المشروعات التي تَعتمِد على المشروعات المُحوَّلة وهكذا إلى أن تُحوِّل الحل (solution) بالكامل.
</p>

<p>
	يُمكِنك اِستخدَام احدى الطرائق التالية لتتعرف على الترتيب الذي ينبغي أن تُحوِّل به المشروعات:
</p>

<ul>
<li>
		تُنشِئ أداة <a href="https://docs.microsoft.com/en-us/visualstudio/modeling/create-layer-diagrams-from-your-code" rel="external nofollow">Dependency Diagrams</a> بفيجوال ستوديو رسم بياني مُوجَّه (directed graph) لشيفرة الحل.
	</li>
	<li>
		يُولِد الأمر التالي ملف بصيغة تبادل البيانات (JSON) يتضَمَّن قائمة بمَراجِع (references) المشروعات:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7407_7" style="">
<span class="pln">msbuild </span><span class="typ">_SolutionPath_</span><span class="pln"> </span><span class="pun">/</span><span class="pln">t</span><span class="pun">:</span><span class="typ">GenerateRestoreGraphFile</span><span class="pln"> </span><span class="pun">/</span><span class="pln">p</span><span class="pun">:</span><span class="typ">RestoreGraphOutputPath</span><span class="pun">=</span><span class="pln">graph</span><span class="pun">.</span><span class="pln">dg</span><span class="pun">.</span><span class="pln">json</span></pre>

<ul>
<li>
		تُعيد أداة <a href="https://docs.microsoft.com/en-us/dotnet/standard/analyzers/portability-analyzer" rel="external nofollow">.NET Portability Analyzer</a> مُخطط للتبعيات (dependency diagram) عند تفعيل الخاصية <code>-r DGML</code> .
	</li>
</ul>
<h3>
	خطوات تحويل مشروع (project)
</h3>

<p>
	يُنصَح باتباع الخطوات التالية عند تحويل مشروع بحيث يُصبِح متوافقًا مع <code>‎.NET Core</code>:
</p>

<ol>
<li>
		<p>
			غَيِّر طريقة تَضْمِين التبعيات من صيغة بيئة عمل <code>‎.NET Framework</code> والموجودة بملف <code>packages.config</code> إلى صيغة <code>PackageReference</code> المُستخدَمة ببيئة عمل <code>‎.NET Core</code>. لاحظ أن بيئة عمل <code>‎.NET Core</code> تُضمِن فقط التبعيات المُستخدمة فعليًا بالمشروع بغرض تقليل عدد التبعيات المُضافة. قد تَستخدِم <a href="https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference" rel="external nofollow">أداة تحويل متوفرة بفيجوال ستوديو</a> للقيام بذلك.
		</p>
	</li>
	<li>
		<p>
			حَوِل صيغة ملف المشروع (project file) إلى الصيغة المُستخدَمة ببيئة عمل <code>‎.NET Core</code>، والتي تُعدّ أبسط من تلك المُستخدَمة ببيئة عمل <code>‎.NET Framework</code>. تَسمَح الصيغة الجديدة بتخصيص بيئة العمل المُستهدَفة أثناء بناء المشروع مما يعني أنه من الممكن أن تَستمر باستهداف بيئة عمل <code>‎.NET Framework</code> حتى تنتهي من عملية التحويل.
		</p>
	</li>
	<li>
		<p>
			اِستهدف بيئة عمل <code>‎.NET Framework</code> إصدار 4.7.2 أو أحدث بجميع المشروعات.
		</p>
	</li>
	<li>
		<p>
			حَدِث جميع تَبعِيات المشروع إلى آخِر إصدار، فربما لا تُدعِّم الإصدارات القديمة من تلك التبعيات -والتي قد يكون مشروعك مُعتمِدًا عليها- مواصفات واجهة تطوير التطبيقات <code>‎.NET Standard</code> بينما قد تُدعِّمها الإصدارات الأحدث. قد تَضطرك بعض تلك التحديثات إلى إجراء تعديلات بالشيفرة.
		</p>
	</li>
	<li>
		<p>
			اِستخدِم أداة <a href="https://docs.microsoft.com/en-us/dotnet/standard/analyzers/portability-analyzer" rel="external nofollow">‎.NET Portability Analyzer</a> لتحليل شيفرات التجميع (assemblies)، ومعرفة ما إذا كانت قابلة للنقل (portable) إلى بيئة عمل <code>‎.NET Core</code>، حيث تُولِد هذه الأداة تقرير يحتوي على ملخص لجميع واجهات تطوير التطبيقات (APIs) غير المُتوفرة بـ <code>NET Core</code> والمُستخدَمة بالمشروع. يَتوفَّر لغالبية تلك الواجهات نظير ببيئة عمل <code>‎.NET Core</code> ستحتاج إلى استخدامه كبديل.
		</p>
	</li>
	<li>
		<p>
			تُمكنك أداة <a href="https://docs.microsoft.com/en-us/dotnet/standard/analyzers/api-analyzer" rel="external nofollow">‎.NET <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> analyzer</a> من تحديد ما إذا كنت تَستخدِم أي من واجهات تطوير التطبيقات (APIs) بطريقة تَتسبب بحدوث اعتراض من النوع <code>PlatformNotSupportedException</code> أثناء زمن التشغيل.
		</p>
	</li>
	<li>
		<p>
			أخيرًا غَيّر بيئة العمل المستهدفة بملف المشروع من:
		</p>
	</li>
</ol>
<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_7407_9" style="">
<span class="pln">   </span><span class="tag">&lt;TargetFramework&gt;</span><span class="pln">net472</span><span class="tag">&lt;/TargetFramework&gt;</span></pre>

<p>
	إلى <code>‎.NET Core</code> أو <code>‎.NET Standard</code>:
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_7407_11" style="">
<span class="pln">   </span><span class="tag">&lt;TargetFramework&gt;</span><span class="pln">netcoreapp3.1</span><span class="tag">&lt;/TargetFramework&gt;</span></pre>

<p>
	يَعتمِد الاختيار ما بين <code>‎.NET Core</code> و <code>‎.NET Standard</code> على الغرض من المشروع. إذا كان المشروع هو مُجرد مكتبة (library) ستُستخدَم بواسطة تطبيقات اخرى، يُفضَّل عندها استهداف مواصفات واجهة تطوير التطبيقات <code>‎.NET Standard</code>. في المقابل، ستضطر إلى استهداف بيئة عمل <code>‎.NET Core</code> إذا كان المشروع يَعتمِد على بعض الواجهات المتوفرة فقط بتلك البيئة، وفي تلك الحالة يُمكِنك أيضًا توفير بناء ثانوي يَستهِدف <code>‎.NET Standard</code> لكن بخاصيات أقل.
</p>

<h2>
	تطبيق طرفية
</h2>

<p>
	تَستعرِض الشيفرة التالية تطبيق طرفية بسيط (Console App) باستخدام بيئة العمل ‎.NET Core:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7407_13" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"\nWhat is your name? "</span><span class="pun">);</span><span class="pln">
        var name </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span><span class="pln">

        var date </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"\nHello, {0}, on {1:d} at {1:t}"</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> date</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"\nPress any key to exit..."</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصل 24 من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">998</guid><pubDate>Thu, 17 Sep 2020 10:09:44 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x634;&#x641;&#x64A;&#x631; Encryption &#x648;&#x627;&#x644;&#x62A;&#x639;&#x645;&#x64A;&#x629; Hashing &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-encryption-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D9%85%D9%8A%D8%A9-hashing-%D9%81%D9%8A-dot-net-r997/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/19.png.643935fe0c8a928ad0b96baf4c08c0d6.png" /></p>

<h2>
	التشفير (Encryption)
</h2>

<h3>
	تشفير البيانات وفكها باستخدام النوع <code>Aes</code>
</h3>

<p>
	تَستعرِض الشيفرة التالية مثال طرفية توضيحي من <a href="https://msdn.microsoft.com/en-us/library/system.security.cryptography.aes(v=vs.110).aspx" rel="external nofollow">شبكة مطوري مايكروسوفت (MSDN)</a>. يَشرَح هذا المثال طريقة تشفير سِلسِلة نصية ثُم فَكّ التشفير باِستخدَام الخوارزمية القياسية "<a href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard" rel="external nofollow">معيار التشفير المُتقدِم Advanced Encryption Standard</a>"، وتُسمَى اختصارًا <code>AES</code>.
</p>

<p>
	يُوفِّر إطار عمل <code>‎.NET</code> النوع <code>Aes</code>، والذي يُنْفِّذ خوارزمية معيار التشفير المُتقدِم <code>AES</code>. تَتكون كُلًا من شيفرتي التشفير وفَكُه مِن عدة خطوات مُشتَركة.
</p>

<p>
	نحتاج عامةً لإِنشاء مَجْرى (stream) بيانات ستمُرّ عَبره البيانات المَطلوب تَشفيِرها أو فَكّ تَشفيِرها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_7" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MemoryStream</span><span class="pln"> msEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">())</span></pre>

<p>
	كذلك سنحتاج إلى تنشئة عملية تَحوِيل مَجْرى (stream transform) -إِمّا مُشفِر أو مُفكِّك للتشفير- من النوع <code>ICryptoTransform</code> بحيث تُطبَّق على البيانات أثناء مرُّورَها بالمَجْرى. يُستخدَم التابعين <code>CreateEncryptor</code> و<code>CreateDecryptor</code> لإنشاء المُشفِر ومُفكِّك التشفير على الترتيب.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_9" style="">
<span class="typ">ICryptoTransform</span><span class="pln"> encryptor </span><span class="pun">=</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="typ">CreateEncryptor</span><span class="pun">(</span><span class="pln">aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_11" style="">
<span class="typ">ICryptoTransform</span><span class="pln"> decryptor </span><span class="pun">=</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="typ">CreateDecryptor</span><span class="pun">(</span><span class="pln">aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span></pre>

<p>
	أخيرًا، نُنشِئ مَجْرى تَشفير من النوع <code>CryptoStream</code> يُوصِل عملية تَحوِيل المَجْرى (stream transform) بمَجْرى البيانات مع تحديد وَضْع التَوصِيل إِمّا للقراءة أو للكتابة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_13" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> csEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">msEncrypt</span><span class="pun">,</span><span class="pln"> encryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">))</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_15" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> csDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">msDecrypt</span><span class="pun">,</span><span class="pln"> decryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span></pre>

<p>
	مثلًا، في حالة التشفير، سنَكتُب البيانات المطلوب تشفيرها على مَجْرى التشفير <code>CryptoStream</code>. يتم تَّنْفيذ عملية تَحوِيل المَجْرى (stream transform) -مُشفِر في هذه الحالة- على البيانات، وتُكتَب النتيجة المُشفَّرة على المَجْرى المُمرَّر لمَجْرى التشفير بوَضْع الكتابة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_17" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MemoryStream</span><span class="pln"> msEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">())</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> csEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">msEncrypt</span><span class="pun">,</span><span class="pln"> encryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamWriter</span><span class="pln"> swEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">csEncrypt</span><span class="pun">))</span><span class="pln">
        swEncrypt</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">plainText</span><span class="pun">);</span><span class="pln">
    encrypted </span><span class="pun">=</span><span class="pln"> msEncrypt</span><span class="pun">.</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في حالة فَكّ التشفير، سيَقرأ مَجْرى التشفير <code>CryptoStream</code> البيانات المطلوب فَكّ تشفيرها من المَجْرى المُمرَّر له بوَضْع القراءة. يتم تَّنْفيذ عملية تَحوِيل المَجْرى (stream transform) -مُفكِّك شَفرة في هذه الحالة- على البيانات. أخيرًا نقرأ البيانات بعد فَكّ التشفير من خلال مَجْرى التشفير.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_19" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MemoryStream</span><span class="pln"> msDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">(</span><span class="pln">cipherText</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> csDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">msDecrypt</span><span class="pun">,</span><span class="pln"> decryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamReader</span><span class="pln"> srDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamReader</span><span class="pun">(</span><span class="pln">csDecrypt</span><span class="pun">))</span><span class="pln">
    plaintext </span><span class="pun">=</span><span class="pln"> srDecrypt</span><span class="pun">.</span><span class="typ">ReadToEnd</span><span class="pun">();</span></pre>

<p>
	الشيفرة بالكامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_21" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Security</span><span class="pun">.</span><span class="typ">Cryptography</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Aes_Example</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AesExample</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎</span><span class="pln">
            </span><span class="kwd">try</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                string original </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Here is some data to encrypt!"</span><span class="pun">;</span><span class="pln">
      </span><span class="com">// ‫أنشئ كائن من النوع Aes المُستخدَم لتوليد كلا من المفتاح ومتجه التهيئة </span><span class="pln">
                </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Aes</span><span class="pln"> myAes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Aes</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">())</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="com">// قم بتشفير سلسلة نصية إلى مصفوفة بايتات</span><span class="pln">
                    byte</span><span class="pun">[]</span><span class="pln"> encrypted </span><span class="pun">=</span><span class="pln"> </span><span class="typ">EncryptStringToBytes_Aes</span><span class="pun">(</span><span class="pln">original</span><span class="pun">,</span><span class="pln">
                                                                myAes</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln">
                                                                myAes</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span><span class="pln">

                   </span><span class="com">// قم بفك تشفير مصفوفة بايتات إلى سلسلة نصية</span><span class="pln">
                    string roundtrip </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DecryptStringFromBytes_Aes</span><span class="pun">(</span><span class="pln">encrypted</span><span class="pun">,</span><span class="pln"> myAes</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> myAes</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span><span class="pln">

                    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Original: {0}"</span><span class="pun">,</span><span class="pln"> original</span><span class="pun">);</span><span class="pln">
                    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Round Trip: {0}"</span><span class="pun">,</span><span class="pln"> roundtrip</span><span class="pun">);</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Error: {0}"</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_23" style="">
<span class="kwd">static</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="typ">EncryptStringToBytes_Aes</span><span class="pun">(</span><span class="pln">string plainText</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> IV</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Check arguments.</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">plainText </span><span class="pun">==</span><span class="pln"> null </span><span class="pun">||</span><span class="pln"> plainText</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="str">"plainText"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Key</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> null </span><span class="pun">||</span><span class="pln"> </span><span class="typ">Key</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="str">"Key"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">IV </span><span class="pun">==</span><span class="pln"> null </span><span class="pun">||</span><span class="pln"> IV</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="str">"IV"</span><span class="pun">);</span><span class="pln">

    byte</span><span class="pun">[]</span><span class="pln"> encrypted</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫أنشئ كائن من النوع Aes باستخدام المفتاح ومتجه التهيئة المحددين </span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Aes</span><span class="pln"> aesAlg </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Aes</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Key</span><span class="pun">;</span><span class="pln">
        aesAlg</span><span class="pun">.</span><span class="pln">IV </span><span class="pun">=</span><span class="pln"> IV</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// أنشئ مُشفر والذي سيستخدم كمحول للمجرى</span><span class="pln">
        </span><span class="typ">ICryptoTransform</span><span class="pln"> encryptor </span><span class="pun">=</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="typ">CreateEncryptor</span><span class="pun">(</span><span class="pln">aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// انشئ المجاري المستخدمة خلال عملية التشفير</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MemoryStream</span><span class="pln"> msEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">())</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> csEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">msEncrypt</span><span class="pun">,</span><span class="pln"> encryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamWriter</span><span class="pln"> swEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">csEncrypt</span><span class="pun">))</span><span class="pln">
                swEncrypt</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">plainText</span><span class="pun">);</span><span class="pln">
            encrypted </span><span class="pun">=</span><span class="pln"> msEncrypt</span><span class="pun">.</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// أعد مصفوفة البايتات المشفرة المُنشأة من مجرى الذاكرة</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> encrypted</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9927_6" style="">
<span class="kwd">static</span><span class="pln"> string </span><span class="typ">DecryptStringFromBytes_Aes</span><span class="pun">(</span><span class="pln">byte</span><span class="pun">[]</span><span class="pln"> cipherText</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> IV</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تحقق من الوسائط</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cipherText </span><span class="pun">==</span><span class="pln"> null </span><span class="pun">||</span><span class="pln"> cipherText</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="str">"cipherText"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Key</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> null </span><span class="pun">||</span><span class="pln"> </span><span class="typ">Key</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="str">"Key"</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">IV </span><span class="pun">==</span><span class="pln"> null </span><span class="pun">||</span><span class="pln"> IV</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="str">"IV"</span><span class="pun">);</span><span class="pln">

    string plaintext </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫أنشئ كائن من النوع Aes باستخدام المفتاح ومتجه التهيئة المحددين </span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Aes</span><span class="pln"> aesAlg </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Aes</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Key</span><span class="pun">;</span><span class="pln">
        aesAlg</span><span class="pun">.</span><span class="pln">IV </span><span class="pun">=</span><span class="pln"> IV</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// أنشئ مفكك الشفرة الذي سيستخدم كمحول للمجرى</span><span class="pln">
        </span><span class="typ">ICryptoTransform</span><span class="pln"> decryptor </span><span class="pun">=</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="typ">CreateDecryptor</span><span class="pun">(</span><span class="pln">aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// انشئ المجاري المستخدمة خلال عملية فك التشفير</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MemoryStream</span><span class="pln"> msDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">(</span><span class="pln">cipherText</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> csDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">msDecrypt</span><span class="pun">,</span><span class="pln"> decryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamReader</span><span class="pln"> srDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamReader</span><span class="pun">(</span><span class="pln">csDecrypt</span><span class="pun">))</span><span class="pln">
            </span><span class="com">// ‫قم بقراءة البايتات من مجرى فك التشفير وأسْندها إلى متغير من النوع string</span><span class="pln">
            plaintext </span><span class="pun">=</span><span class="pln"> srDecrypt</span><span class="pun">.</span><span class="typ">ReadToEnd</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> plaintext</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُحدِّد الخوارزمية <code>AES</code> طريقة لتشفير البيانات الالكترونية. أُسِست عام 2001 بواسطة المعهد الوطني للمعايير والتقنية <code>NIST</code> بالولايات المتحدة الامريكية، ومازالت تُعدّ الخوارزمية القياسية للتشفير التَماثلي (symmetric encryption).
</p>

<p>
	ملاحظات:
</p>

<ul>
<li>
		تَتوفَّر عِدة أوضاع تَشفير <code>cipher mode</code> ضِمْن خوارزمية <code>AES</code>. تَستطيع تَحديد وَضْع التشفير بإِسْناد إِحدى قيم التعداد <code>CipherMode</code> إلى الخاصية <code>Mode</code>. لا تَستخدِم أبدًا وَضْع التشفير <code>Electronic codebook - ECB</code> - مما يَعنِي عدم إِختيار <code>CipherMode.ECB</code>-؛ لأنه يُنتِج عملية تَحوِيل مَجْرى ضعيفة.
	</li>
	<li>
		يجب أن تَستخدِم مُولِّد تَشفير عشوائي -أو اِستخدِم الشيفرة بالأسفل (إنشاء مفتاح من كلمة سرّ / سلسلة نصية إضافية (Salt) عشوائية)- لتنشئة مفتاح (Key) جيد غيْر ضعيف. يُفضَّل أيضًا أن يَكُون حجم المفتاح 256 بت. تستطيع تخصيص حَجم المفتاح مِن خلال الخاصية <code>KeySize</code> كما تُوفِّر الخاصية <code>LegalKeySizes</code> قائمة بالأحجام المُدعَّمة.
	</li>
	<li>
		يُمكِنك اِستخدَام سِلسِلة نصية إضافية (salt) -كالمثال بالأسفل (إنشاء مفتاح من كلمة سرّ / سلسلة نصية إضافية (Salt) عشوائية)- لتهيئة مُتّجَه التهيئة (initialization vector - IV).
	</li>
</ul>
<h3>
	مثال آخر باستخدام خوارزمية <code>AES</code>
</h3>

<p>
	شيفرة التشفير:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_27" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">Encrypt</span><span class="pun">(</span><span class="pln">string cipherText</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cipherText </span><span class="pun">==</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">

    byte</span><span class="pun">[]</span><span class="pln"> clearBytes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="typ">Unicode</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">cipherText</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Aes</span><span class="pln"> encryptor </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Aes</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Rfc2898DeriveBytes</span><span class="pln"> pdb </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Rfc2898DeriveBytes</span><span class="pun">(</span><span class="typ">CryptKey</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">0x49</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x76</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x61</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x6e</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x4d</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x65</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x64</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x76</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x65</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x64</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x65</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x76</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

        encryptor</span><span class="pun">.</span><span class="typ">Key</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> pdb</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="lit">32</span><span class="pun">);</span><span class="pln">
        encryptor</span><span class="pun">.</span><span class="pln">IV </span><span class="pun">=</span><span class="pln"> pdb</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="lit">16</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MemoryStream</span><span class="pln"> ms </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> cs </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">ms</span><span class="pun">,</span><span class="pln"> encryptor</span><span class="pun">.</span><span class="typ">CreateEncryptor</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                cs</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">clearBytes</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> clearBytes</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span><span class="pln">
                cs</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            cipherText </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Convert</span><span class="pun">.</span><span class="typ">ToBase64String</span><span class="pun">(</span><span class="pln">ms</span><span class="pun">.</span><span class="typ">ToArray</span><span class="pun">());</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> cipherText</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	شيفرة فَكّ التشفير:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_29" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">Decrypt</span><span class="pun">(</span><span class="pln">string cipherText</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cipherText </span><span class="pun">==</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">

    byte</span><span class="pun">[]</span><span class="pln"> cipherBytes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Convert</span><span class="pun">.</span><span class="typ">FromBase64String</span><span class="pun">(</span><span class="pln">cipherText</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Aes</span><span class="pln"> encryptor </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Aes</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Rfc2898DeriveBytes</span><span class="pln"> pdb </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Rfc2898DeriveBytes</span><span class="pun">(</span><span class="typ">CryptKey</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">0x49</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x76</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x61</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x6e</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x4d</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x65</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x64</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x76</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x65</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x64</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x65</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0x76</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

        encryptor</span><span class="pun">.</span><span class="typ">Key</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> pdb</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="lit">32</span><span class="pun">);</span><span class="pln">
        encryptor</span><span class="pun">.</span><span class="pln">IV </span><span class="pun">=</span><span class="pln"> pdb</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="lit">16</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MemoryStream</span><span class="pln"> ms </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CryptoStream</span><span class="pln"> cs </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">ms</span><span class="pun">,</span><span class="pln"> encryptor</span><span class="pun">.</span><span class="typ">CreateDecryptor</span><span class="pun">(),</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                cs</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">cipherBytes</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> cipherBytes</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span><span class="pln">
                cs</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            cipherText </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="typ">Unicode</span><span class="pun">.</span><span class="typ">GetString</span><span class="pun">(</span><span class="pln">ms</span><span class="pun">.</span><span class="typ">ToArray</span><span class="pun">());</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> cipherText</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُستخدَم كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_31" style="">
<span class="pln">var textToEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="str">"TestEncrypt"</span><span class="pun">;</span><span class="pln">
var encrypted </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encrypt</span><span class="pun">(</span><span class="pln">textToEncrypt</span><span class="pun">);</span><span class="pln">
var decrypted </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Decrypt</span><span class="pun">(</span><span class="pln">encrypted</span><span class="pun">);</span></pre>

<h3>
	تشفير البيانات وفكها باستخدام النوع <code>RijndaelManaged</code>
</h3>

<p>
	يَتطلَّب فضاء الاسم <code>System.Security.Cryptography</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_33" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Encryption</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> string </span><span class="typ">SecretKey</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"topSecretKeyusedforEncryptions"</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> string </span><span class="typ">SecretIv</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"secretVectorHere"</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Encrypt</span><span class="pun">(</span><span class="pln">string data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> string</span><span class="pun">.</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> data </span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Convert</span><span class="pun">.</span><span class="typ">ToBase64String</span><span class="pun">(</span><span class="pln">
            </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">EncryptStringToBytesAes</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">GetCryptographyKey</span><span class="pun">(),</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">GetCryptographyIv</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Decrypt</span><span class="pun">(</span><span class="pln">string data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> string</span><span class="pun">.</span><span class="typ">IsNullOrEmpty</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> data </span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">DecryptStringFromBytesAes</span><span class="pun">(</span><span class="typ">Convert</span><span class="pun">.</span><span class="typ">FromBase64String</span><span class="pun">(</span><span class="pln">data</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">GetCryptographyKey</span><span class="pun">(),</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">GetCryptographyIv</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="typ">GetCryptographyKey</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">ASCII</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">SecretKey</span><span class="pun">.</span><span class="typ">Replace</span><span class="pun">(</span><span class="str">'e'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'!'</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="typ">GetCryptographyIv</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">ASCII</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">SecretIv</span><span class="pun">.</span><span class="typ">Replace</span><span class="pun">(</span><span class="str">'r'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'!'</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">    </span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_35" style="">
<span class="kwd">private</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="typ">EncryptStringToBytesAes</span><span class="pun">(</span><span class="pln">string plainText</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> iv</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">MemoryStream</span><span class="pln"> encrypt</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">RijndaelManaged</span><span class="pln"> aesAlg </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

        aesAlg </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RijndaelManaged</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Key</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> key</span><span class="pun">,</span><span class="pln">
            IV </span><span class="pun">=</span><span class="pln"> iv
        </span><span class="pun">};</span><span class="pln">
        var encryptor </span><span class="pun">=</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="typ">CreateEncryptor</span><span class="pun">(</span><span class="pln">aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span><span class="pln">

        encrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var csEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">encrypt</span><span class="pun">,</span><span class="pln"> encryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var swEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">csEncrypt</span><span class="pun">))</span><span class="pln">
            swEncrypt</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">plainText</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> finally </span><span class="pun">{</span><span class="pln">
        aesAlg</span><span class="pun">?.</span><span class="typ">Clear</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> encrypt</span><span class="pun">.</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_37" style="">
<span class="kwd">private</span><span class="pln"> string </span><span class="typ">DecryptStringFromBytesAes</span><span class="pun">(</span><span class="pln">byte</span><span class="pun">[]</span><span class="pln"> cipherText</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> iv</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="typ">RijndaelManaged</span><span class="pln"> aesAlg </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
    string plaintext</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        aesAlg </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RijndaelManaged</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Key</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> key</span><span class="pun">,</span><span class="pln">
            IV </span><span class="pun">=</span><span class="pln"> iv
        </span><span class="pun">};</span><span class="pln">
        var decryptor </span><span class="pun">=</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="typ">CreateDecryptor</span><span class="pun">(</span><span class="pln">aesAlg</span><span class="pun">.</span><span class="typ">Key</span><span class="pun">,</span><span class="pln"> aesAlg</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var msDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MemoryStream</span><span class="pun">(</span><span class="pln">cipherText</span><span class="pun">))</span><span class="pln"> 
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var csDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CryptoStream</span><span class="pun">(</span><span class="pln">msDecrypt</span><span class="pun">,</span><span class="pln"> decryptor</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CryptoStreamMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span><span class="pln"> 
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var srDecrypt </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamReader</span><span class="pun">(</span><span class="pln">csDecrypt</span><span class="pun">))</span><span class="pln">
            plaintext </span><span class="pun">=</span><span class="pln"> srDecrypt</span><span class="pun">.</span><span class="typ">ReadToEnd</span><span class="pun">();</span><span class="pln">

    </span><span class="pun">}</span><span class="pln"> finally </span><span class="pun">{</span><span class="pln">
        aesAlg</span><span class="pun">?.</span><span class="typ">Clear</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> plaintext</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُستخدَم كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_39" style="">
<span class="pln">var textToEncrypt </span><span class="pun">=</span><span class="pln"> </span><span class="str">"hello World"</span><span class="pun">;</span><span class="pln">
</span><span class="com">//-&gt; zBmW+FUxOvdbpOGm9Ss/vQ==</span><span class="pln">
var encrypted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Encryption</span><span class="pun">().</span><span class="typ">Encrypt</span><span class="pun">(</span><span class="pln">textToEncrypt</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">//-&gt; hello World</span><span class="pln">
var decrypted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Encryption</span><span class="pun">().</span><span class="typ">Decrypt</span><span class="pun">(</span><span class="pln">encrypted</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	تنبيه: يُنفِّذ النوع <code>Rijndael</code> النسخة الأقدم من خوارزمية <code>AES</code>، ولذلك ينبغي استعمال النوع <code>Aes</code> الذي يُنفِّذ النسخة الحديثة.
</p>

<h3>
	إنشاء مفتاح من كلمة سر / سلسلة نصية إضافية (Salt) عشوائية
</h3>

<p>
	تَستعرِض الشيفرة التالية مثال طرفية توضيحي من <a href="https://msdn.microsoft.com/en-us/library/system.security.cryptography.passwordderivebytes(v=vs.110).aspx" rel="external nofollow">شبكة مطوري مايكروسوفت (MSDN)</a>. يَشرح هذا المثال كيفية تنشئة مفتاح (key) آمِن اعتمادًا على كلمة سرّ مُحدَّدة من قِبَل المُستخدِم، بالإضافة إلى طريقة تنشئة سِلسِلة نصية إضافية (salt أو يدعى غفل باللغة العربية، انظر كتاب «علم التعمية واستخراج المعمى عند العرب») عشوائية باِستخدَام مُولِّد تشفير عشوائي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9927_9" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Security</span><span class="pun">.</span><span class="typ">Cryptography</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PasswordDerivedBytesExample</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="typ">String</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// اجلب كلمة السر من المستخدم</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Enter a password to produce a key:"</span><span class="pun">);</span><span class="pln">

        byte</span><span class="pun">[]</span><span class="pln"> pwd </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="typ">Unicode</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">());</span><span class="pln">
        byte</span><span class="pun">[]</span><span class="pln"> salt </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateRandomSalt</span><span class="pun">(</span><span class="lit">7</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// TripleDESCryptoServiceProvider أنشئ كائنًا من النوع</span><span class="pln">
        </span><span class="typ">TripleDESCryptoServiceProvider</span><span class="pln"> tdes </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TripleDESCryptoServiceProvider</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Creating a key with PasswordDeriveBytes..."</span><span class="pun">);</span><span class="pln">

  </span><span class="com">// ‫أنشئ كائنًا من النوع PasswordDeriveBytes ثم أنشئ مفتاح لخوارزمية TripleDES</span><span class="pln">
            </span><span class="com">// من كلمة سر وسلسلة نصية إضافية</span><span class="pln">
            </span><span class="typ">PasswordDeriveBytes</span><span class="pln"> pdb </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">PasswordDeriveBytes</span><span class="pun">(</span><span class="pln">pwd</span><span class="pun">,</span><span class="pln"> salt</span><span class="pun">);</span><span class="pln">

            </span><span class="com">// ‫أنشئ المفتاح وأسنده إلى الخاصية Key الموجودة بكائن موفر خدمة التشفير</span><span class="pln">
            tdes</span><span class="pun">.</span><span class="typ">Key</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> pdb</span><span class="pun">.</span><span class="typ">CryptDeriveKey</span><span class="pun">(</span><span class="str">"TripleDES"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"SHA1"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">192</span><span class="pun">,</span><span class="pln"> tdes</span><span class="pun">.</span><span class="pln">IV</span><span class="pun">);</span><span class="pln">

            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Operation complete."</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        finally
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">ClearBytes</span><span class="pun">(</span><span class="pln">pwd</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">ClearBytes</span><span class="pun">(</span><span class="pln">salt</span><span class="pun">);</span><span class="pln">
            tdes</span><span class="pun">.</span><span class="typ">Clear</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9927_11" style="">
<span class="com">/// توليد غفل (سلسلة نصية إضافية) بالطول المحدد</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="typ">CreateRandomSalt</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> length</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    byte</span><span class="pun">[]</span><span class="pln"> randBytes</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">length </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
        randBytes </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="pln">length</span><span class="pun">];</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
        randBytes </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">

    </span><span class="com">// RNGCryptoServiceProvider إنشاء كائن من النوع</span><span class="pln">
    </span><span class="typ">RNGCryptoServiceProvider</span><span class="pln"> rand </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RNGCryptoServiceProvider</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// املأ المخزن بالبايتات العشوائية</span><span class="pln">
    rand</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">randBytes</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> randBytes</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9927_13" style="">
<span class="com">/// امسح البايتات من المخزن لكي لا تُقرَأ مستقبلًا من الذاكرة</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ClearBytes</span><span class="pun">(</span><span class="pln">byte</span><span class="pun">[]</span><span class="pln"> buffer</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">buffer </span><span class="pun">==</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArgumentNullException</span><span class="pun">(</span><span class="str">"buffer"</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// اضبط قيمة كل بايت إلى القيمة 0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">&lt;</span><span class="pln"> buffer</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">;</span><span class="pln"> x</span><span class="pun">++)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        buffer</span><span class="pun">[</span><span class="pln">x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملاحظات:
</p>

<ul>
<li>
		تَستقبِل الدالة <code>PasswordDeriveBytes</code> المَبنية مُسبَقًا (built-in) كلمة سرّ، وتَستخدِم خوارزمية <code>PBKDF1</code> القياسية لتولِّيد المفتاح. تَقوم هذه الدالة بشكل افتراضي بمائة تكرار أثناء تولِّيد المفتاح؛ وذلك لتُبطئ من فاعلية هَجمَات القوى الغاشمة (brute force attacks). بالإضافة إلى ذلك، يُعزز اِستخدَام السِلسِلة النصية الإضافية (salt) المُولَّدة عشوائيًا من قوة المفتاح.
	</li>
	<li>
		تَستخدِم الدالة <code>CryptDeriveKey</code> خوارزمية التَقطيع (hashing) المُمرَّرة إليها -تم اختيار <code>SHA1</code> بالمثال- لتَحوِيل المفتاح المُولَّد من الدالة <code>PasswordDeriveBytes</code> إلى مفتاح مُتوافِق مع خوارزمية التشفير المُمرَّرة إليها -تم اختيار <code>TripleDES</code> بالمثال-، يمكنك أيضًا تخصيص كلًا من حجم المفتاح والقيمة المبدئية لمُتٍّجَه التهيئة (initialization vector - IV) بتمريرهما كمُعامِلين للدالة. في المثال بالأعلى، مُرِّرت القيمة 192 بايت كما اُستخدِم مُوفِّر خدمة التشفير من النوع <code>TripleDESCryptoServiceProvider</code> لتهيئة مُتّجَه التهيئة.
	</li>
	<li>
		عندما تحتاج إلى مفتاح قوي مُولَّد عشوائيًا لاِستخدَامُه لتشفير كمية ضخمة من البيانات، اِستخدِم هذه الطريقة لتولِّيده مِن مجرد كلمة سرّ. يُمكِن أيضًا اِستخدَام هذه الطريقة لتوليد كلمات سر لعِدّة مُستخدِمين للولوج إلى نفس البيانات.
	</li>
	<li>
		للأسف، لا تُدعِّم الدالة <code>CryptDeriveKey</code> خوارزمية <code>AES</code> حاليًا (<a href="https://social.msdn.microsoft.com/Forums/vstudio/en-US/61d85001-2eae-4419-b4bf-ce98d46f4d21/passwordderivebytescryptderivekey-derives-an-aes-key-but-gets-quotobject-identifier-oid-is?forum=netfxbcl" rel="external nofollow">تَحقَّق هنا</a>). يُمكِن التحايل على ذلك بالاعتماد على حَاوِي خوارزمية <code>TripleDES</code>، مع أنه سيُؤدِي إلى تَبَعيّة لهذه الخوارزمية وسيُقصِرك على مُستَوَى حمايتها، فمثلًا لن تستطيع تَوليد مفاتيح بأحجام أكبر من تلك المُدعَّمة بخوارزمية <code>TripleDES</code> على الرغم من دَعََّم تلك الأحجام بخوارزمية <code>AES</code>.
	</li>
</ul>
<h2>
	دوال التعمية (Hashing)
</h2>

<h3>
	توليد تدقيق المجموع (checksum) لملف باستخدام خوارزمية <code>SHA1</code>
</h3>

<p>
	تَتطلَّب فضاء الاسم <code>System.Security.Cryptography</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_47" style="">
<span class="kwd">public</span><span class="pln"> string </span><span class="typ">GetSha1Hash</span><span class="pun">(</span><span class="pln">string filePath</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileStream</span><span class="pln"> fs </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">OpenRead</span><span class="pun">(</span><span class="pln">filePath</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        SHA1 sha </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> SHA1Managed</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">BitConverter</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(</span><span class="pln">sha</span><span class="pun">.</span><span class="typ">ComputeHash</span><span class="pun">(</span><span class="pln">fs</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	توليد القيمة المعماة (hash أو المقطعة) لسِلسِلة نصية
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9980_49" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">TextToHash</span><span class="pun">(</span><span class="pln">string text</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var sh </span><span class="pun">=</span><span class="pln"> SHA1</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">();</span><span class="pln">
    var hash </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringBuilder</span><span class="pun">();</span><span class="pln">
    byte</span><span class="pun">[]</span><span class="pln"> bytes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">UTF8</span><span class="pun">.</span><span class="typ">GetBytes</span><span class="pun">(</span><span class="pln">text</span><span class="pun">);</span><span class="pln">
    byte</span><span class="pun">[]</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> sh</span><span class="pun">.</span><span class="typ">ComputeHash</span><span class="pun">(</span><span class="pln">bytes</span><span class="pun">);</span><span class="pln">
    foreach </span><span class="pun">(</span><span class="pln">byte a in b</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var h </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(</span><span class="str">"x2"</span><span class="pun">);</span><span class="pln">
        hash</span><span class="pun">.</span><span class="typ">Append</span><span class="pun">(</span><span class="pln">h</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> hash</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملحوظة: الشيفرة بالكامل موجودة بـ<a href="https://github.com/mahdiabasi/SHA1Tool" rel="external nofollow">مستودع mahdiabasi/SHA1Tool في GitHub</a>.
</p>

<p>
	ترجمة -وبتصرف- للفصلين Encryption / Cryptography و Work with SHA1 in C#‎ من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">997</guid><pubDate>Thu, 17 Sep 2020 09:53:44 +0000</pubDate></item><item><title>&#x627;&#x644;&#x633;&#x644;&#x633;&#x644;&#x629; Serialization &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%B3%D9%84%D8%B3%D9%84%D8%A9-serialization-%D9%81%D9%8A-dot-net-r996/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/18.png.d503feee2fa5a59c0a900b79f05fe72b.png" /></p>

<h2>
	السلسلة إلى JSON
</h2>

<h3>
	استخدام <code>Json.NET</code>
</h3>

<p>
	<code>Newtonsoft.Json</code> هي حزمة قوية، وسريعة، وسهلة الاستخدام مما جعلها الأداة الأكثر شيوعًا عند التعامل مع "السَلاسِل النصية بصيغة تبادل البيانات (JSON)" بإطار عمل ‎.NET. يُعدّ اِستخدامها سهلًا نوعًا ما؛ لكونها تعتمد على التوابع الساكنة (static) سواء للسَلسَلة (serialize)، أو لإلغاء السَلسَلة (de-serialize).
</p>

<p>
	بالتحديد يُسَلسِل التابع <code>JsonConvert.SerializeObject</code> الكائن المُمرَّر له ويُعيد سِلسِلة نصية، بينما يُلغي التابع <code>JsonConvert.DeserializeObject&lt;T&gt;‎</code> سَلسَلة المُعامِل المُمرَّر له ويُحاول تحليله إلى نوع يُحدَّد من خلال مُعامِل النوع (type parameter) كالمثالين التاليين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_7" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">Newtonsoft</span><span class="pun">.</span><span class="typ">Json</span><span class="pun">;</span><span class="pln">

var rawJSON </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{\"Name\":\"Fibonacci Sequence\",\"Numbers\":[0, 1, 1, 2, 3, 5, 8, 13]}"</span><span class="pun">;</span><span class="pln">

var fibo </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">DeserializeObject</span><span class="pun">&lt;</span><span class="typ">Dictionary</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> object</span><span class="pun">&gt;&gt;(</span><span class="pln">rawJSON</span><span class="pun">);</span><span class="pln">

var rawJSON2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">SerializeObject</span><span class="pun">(</span><span class="pln">fibo</span><span class="pun">);</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_9" style="">
<span class="pln">internal </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sequence</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Name</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="typ">Numbers</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

string rawJSON </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{\"Name\":\"Fibonacci Sequence\",\"Numbers\":[0, 1, 1, 2, 3, 5, 8, 13]}"</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Sequence</span><span class="pln"> sequence </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">DeserializeObject</span><span class="pun">&lt;</span><span class="typ">Sequence</span><span class="pun">&gt;(</span><span class="pln">rawJSON</span><span class="pun">);</span></pre>

<p>
	اطلع على مزيد من المعلومات عن <code>JSON.NET</code> من خلال <a href="http://www.newtonsoft.com/json" rel="external nofollow">موقعها الرسمي</a>.
</p>

<p>
	يُدعِّم اطار عمل ‎.NET النوع <code>JSON.NET</code> منذ إصدار 2.
</p>

<h3>
	استخدام السمات (attributes) مع <code>Json.NET</code>
</h3>

<p>
	تتوفَّر بعض السمات (attributes) لزخرفة (decoration) كلًا من الأصناف وخاصياتها؛ مما يُمكنك من التحكم بشكل "السِلسِلة النصية بصيغة JSON" النهائية الناتجة عن السَلسَلة.
</p>

<p>
	مثلًا، تُخصِص السمة <code>JsonProperty</code> اسمًا للخاصية المُزخَرفة بدلًا من اسمها الأصلي، في حين تُهمَل الخاصيات المزخرفة بالسمة <code>JsonIgnore</code>.
</p>

<p>
	في المثال التالي: لا يحتوي ناتج السَلسَلة <code>{"name":"Andrius","age":99}</code> على الخاصية <code>Address</code>؛ لأنها مُزخرفة بالسمة <code>JsonIgnore</code>، كما اُستُخدِمت الأسماء <code>name</code> و <code>age</code> بدلًا من الأسماء الأصلية للخاصيات لأنها زُخرِفت بالسمة <code>JsonProperty</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_11" style="">
<span class="pun">[</span><span class="typ">JsonObject</span><span class="pun">(</span><span class="str">"person"</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Person</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">JsonProperty</span><span class="pun">(</span><span class="str">"name"</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">PersonName</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">JsonProperty</span><span class="pun">(</span><span class="str">"age"</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">PersonAge</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">JsonIgnore</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Address</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Person</span><span class="pln"> person </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="typ">PersonName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Andrius"</span><span class="pun">,</span><span class="pln"> 
    </span><span class="typ">PersonAge</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">99</span><span class="pun">,</span><span class="pln"> 
    </span><span class="typ">Address</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Some address"</span><span class="pln"> 
</span><span class="pun">};</span><span class="pln">

string rawJson </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">SerializeObject</span><span class="pun">(</span><span class="pln">person</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">rawJson</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {"name":"Andrius","age":99}</span></pre>

<p>
	اطلع على <a href="https://www.newtonsoft.com/json/help/html/serializationattributes.htm" rel="external nofollow">مزيد من المعلومات عن سمات السَلسَلة</a> التي يُمكنك استخدامها.
</p>

<h3>
	استخدام المُعامِل <code>JsonSerializerSettings</code> مع <code>Json.NET</code>
</h3>

<p>
	تتوفَّر بصمة أُخْرَى من التابع <code>JsonConvert.SerializeObject</code> والتي تَستقبِل -بالإضافة إلى الكائن المراد سَلسَلته- مُعامِلًا آخَر من النوع <code>JsonSerializerSettings</code> للتحكم بعملية السَلسَلة. يحتوي النوع <code>JsonSerializerSettings</code> على العديد من الخاصيات المُصممة خصيصًا لحل بعض أكثر المشاكل شيوعًا.
</p>

<p>
	مثلًا، الخاصية <code>ContractResolver</code> من نوع الواجهة <code>IContractResolver</code>، والتي يتوفَّر لها أكثر من مُنفِّذ (implementation). إحداها هو النوع <code>DefaultContractResolver</code> المُستخدَم افتراضيًا، بالإضافة إلى النوع <code>CamelCasePropertyNamesContractResolver</code> الذي قد يُفيدك عند التحويل من كائنات c#‎ إلى صيغة JSON والعكس؛ نظرًا لشيوع استخدَام النمط <code>PascalCase</code> لدى مبرمجي c#‎ بينما في الغالب ما تكون صيغة تبادل البيانات JSON بنمط سنام الجمل <code>CamelCase</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_13" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">Newtonsoft</span><span class="pun">.</span><span class="typ">Json</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Newtonsoft</span><span class="pun">.</span><span class="typ">Json</span><span class="pun">.</span><span class="typ">Serialization</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Person</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Name</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Age</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">JsonIgnore</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Address</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ToJson</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Person</span><span class="pln"> person </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Person</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
        </span><span class="typ">Name</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Andrius"</span><span class="pun">,</span><span class="pln"> 
        </span><span class="typ">Age</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">99</span><span class="pun">,</span><span class="pln"> 
        </span><span class="typ">Address</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Some address"</span><span class="pln"> 
    </span><span class="pun">};</span><span class="pln">

    var resolver </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CamelCasePropertyNamesContractResolver</span><span class="pun">();</span><span class="pln">

    var settings </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">JsonSerializerSettings</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">ContractResolver</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> resolver </span><span class="pun">};</span><span class="pln">

    string json </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">SerializeObject</span><span class="pun">(</span><span class="pln">person</span><span class="pun">,</span><span class="pln"> settings</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">json</span><span class="pun">);</span><span class="pln"> </span><span class="com">// {"name":"Andrius","age":99}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال آخر هو الخاصية <code>NullValueHandling</code> المُستخدَمة لضَبط طريقة التعامُل مع القيم الفارغة <code>null</code>، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_15" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">T obj</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    string result </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">SerializeObject</span><span class="pun">(</span><span class="pln">obj</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">JsonSerializerSettings</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">NullValueHandling</span><span class="pln">
        </span><span class="pun">=</span><span class="pln"> </span><span class="typ">NullValueHandling</span><span class="pun">.</span><span class="typ">Ignore</span><span class="pun">});</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال أخير هو الخاصية <code>ReferenceLoopHandling</code> التي تُستخدَم لضَبط طريقة التعامل مع تكرار الإشارة الذاتية (self referencing loop). مثلًا، إذا أردت تَمثيل برنامج دراسي مُلحق به عدد من الطلبة، سيكون لديك النوع <code>Student</code> يحوي خاصية من النوع <code>Course</code> والذي بدوره يحمل خاصية <code>Students</code> من النوع <code>List&lt;Student&gt;‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_17" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">T obj</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    string result </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">SerializeObject</span><span class="pun">(</span><span class="pln">
        obj</span><span class="pun">,</span><span class="pln"> 
        </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">JsonSerializerSettings</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">ReferenceLoopHandling</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> 
                </span><span class="typ">ReferenceLoopHandling</span><span class="pun">.</span><span class="typ">Ignore</span><span class="pun">});</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُمكنك تخصيص أكثر من خاصية سَلسَلة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_19" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> string </span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">T obj</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    string result </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">SerializeObject</span><span class="pun">(</span><span class="pln">
        obj</span><span class="pun">,</span><span class="pln"> 
        </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">JsonSerializerSettings</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
            </span><span class="typ">NullValueHandling</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">NullValueHandling</span><span class="pun">.</span><span class="typ">Ignore</span><span class="pun">,</span><span class="pln">
            </span><span class="typ">ReferenceLoopHandling</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ReferenceLoopHandling</span><span class="pun">.</span><span class="typ">Ignore</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الربط الديناميكي (Dynamic Binding)
</h3>

<p>
	تُوفِّر <code>Json.NET</code> خاصية الربط الديناميكي، مما يَسمَح بإلغاء سَلسَلة "سِلسِلة نصية بصيغة JSON" وتحويلها إلى نوع ديناميكي لم يُعلَّن عن خاصياته صراحةً. يتم ذلك إِما باستخدام النوع <code>DynamicObject</code> أو النوع <code>ExpandoObject</code>.
</p>

<p>
	السَلسَلة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_21" style="">
<span class="pln">dynamic jsonObject </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ExpandoObject</span><span class="pun">();</span><span class="pln">
jsonObject</span><span class="pun">.</span><span class="typ">Title</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Merchent of Venice"</span><span class="pun">;</span><span class="pln">
jsonObject</span><span class="pun">.</span><span class="typ">Author</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"William Shakespeare"</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="typ">JsonConvert</span><span class="pun">.</span><span class="typ">SerializeObject</span><span class="pun">(</span><span class="pln">jsonObject</span><span class="pun">));</span></pre>

<p>
	في المثال التالي، حُُوِّلَت المفاتيح (keys) الموجودة "بالسِلسِلة النصية بصيغة JSON" إلى مُتَغيّرات أعضاء (member variables) بالنوع الديناميكي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_23" style="">
<span class="pln">var rawJson </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{\"Name\":\"Fibonacci Sequence\",\"Numbers\":[0, 1, 1, 2, 3, 5, 8, 13]}"</span><span class="pun">;</span><span class="pln">
dynamic parsedJson </span><span class="pun">=</span><span class="pln"> </span><span class="typ">JObject</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="pln">rawJson</span><span class="pun">);</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Name: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> parsedJson</span><span class="pun">.</span><span class="typ">Name</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Name: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> parsedJson</span><span class="pun">.</span><span class="typ">Numbers</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span></pre>

<p>
	قد يكون الربط الديناميكي مفيدًا خاصةً إذا كان البرنامج يَستقبِل ويُنتج العديد من "السَلاسِل النصية بصيغة JSON"، ولكن من الأفضل التحقق (validate) من تلك السَلاسِل النصية الناتجة عن السَلسَلة وكذلك من الكائنات الديناميكية الناتجة عن إلغائها.
</p>

<h3>
	استخدام <code>JavascriptSerializer</code>
</h3>

<p>
	يتوفَّر أيضًا النوع <code>JavascriptSerializer</code> -الموجود بفضاء الاسم <code>System.Web.Script.Serialization</code>- والذي يُعرِّف التابع <code>Deserialize&lt;T&gt;(input)‎</code>. يُلِّغي هذا التابع سَلسَلة "سِلسِلة نصية بصيغة تبادل البيانات (JSON)"، ويُحَوِّلها لكائن نوعه مُحدَّد بمُعامِل النوع (type parameter).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_25" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Collections</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Web</span><span class="pun">.</span><span class="typ">Script</span><span class="pun">.</span><span class="typ">Serialization</span><span class="pun">;</span><span class="pln">

string rawJSON </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{\"Name\":\"Fibonacci Sequence\",\"Numbers\":[0, 1, 1, 2, 3, 5, 8, 13]}"</span><span class="pun">;</span><span class="pln">

</span><span class="typ">JavaScriptSerializer</span><span class="pln"> JSS </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">JavaScriptSerializer</span><span class="pun">();</span><span class="pln">

</span><span class="typ">Dictionary</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> object</span><span class="pun">&gt;</span><span class="pln"> parsedObj </span><span class="pun">=</span><span class="pln"> JSS</span><span class="pun">.</span><span class="typ">Deserialize</span><span class="pun">&lt;</span><span class="typ">Dictionary</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> object</span><span class="pun">&gt;&gt;(</span><span class="pln">rawJSON</span><span class="pun">);</span><span class="pln">

string name </span><span class="pun">=</span><span class="pln"> parsedObj</span><span class="pun">[</span><span class="str">"Name"</span><span class="pun">].</span><span class="pln">toString</span><span class="pun">();</span><span class="pln">
</span><span class="typ">ArrayList</span><span class="pln"> numbers </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ArrayList</span><span class="pun">)</span><span class="pln">parsedObj</span><span class="pun">[</span><span class="str">"Numbers"</span><span class="pun">]</span></pre>

<p>
	يُدعِّم اطار عمل ‎.NET النوع <code>JavaScriptSerializer</code> منذ إصدار 3.5.
</p>

<h2>
	السلسلة إلى XML
</h2>

<h3>
	استخدام <code>XmlSerializer</code>
</h3>

<p>
	يُستخدَم النوع <code>XmlSerializer</code> -الموجود بفضاء الاسم <code>System.Xml.Serialization</code> - لسَلسَلة كائن إلى ملف (document) نصي بصيغة لغة الترميز القابلة للامتداد <code>Extensible Markup Language - XML</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_27" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SerializeFoo</span><span class="pun">(</span><span class="pln">string fileName</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> foo</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var serializer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XmlSerializer</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var stream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">(</span><span class="pln">fileName</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FileMode</span><span class="pun">.</span><span class="typ">Create</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        serializer</span><span class="pun">.</span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">stream</span><span class="pun">,</span><span class="pln"> foo</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُمكن إلغاء السَلسَلة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_29" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="typ">DeserializeFoo</span><span class="pun">(</span><span class="pln">string fileName</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var serializer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XmlSerializer</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var stream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">OpenRead</span><span class="pun">(</span><span class="pln">fileName</span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Foo</span><span class="pun">)</span><span class="pln">serializer</span><span class="pun">.</span><span class="typ">Deserialize</span><span class="pun">(</span><span class="pln">stream</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	استخدام السمات مع <code>XmlSerializer</code>
</h3>

<p>
	تتوفَّر بعض السمات (attributes) لزخرفة (decoration) خاصيات الأنواع؛ مما يُمكنك من التحكم بالصورة النهائية لملف XML الناتج عن السَلسَلة.
</p>

<p>
	مثلًا، تُخصِص السمة <code>XmlArray</code> اسمًا للخاصيات من النوع <code>Array</code> -أو أي نوع قد يُعيد <code>Array</code>- بدلًا من اسمها الأصلي. في المثال التالي، اُستخدِم الاسم <code>Articles</code> بدلًا من الاسم <code>Products</code> نظرًا لأن الخاصية المُناظِرة زُخرِفت بالسمة <code>XmlArray</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_31" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Store</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">XmlArray</span><span class="pun">(</span><span class="str">"Articles"</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">Product</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">Products</span><span class="pln"> </span><span class="pun">{</span><span class="pln">get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_7128_33" style="">
<span class="tag">&lt;Store&gt;</span><span class="pln">
    </span><span class="tag">&lt;Articles&gt;</span><span class="pln">
        </span><span class="tag">&lt;Product/&gt;</span><span class="pln">
        </span><span class="tag">&lt;Product/&gt;</span><span class="pln">
    </span><span class="tag">&lt;/Articles&gt;</span><span class="pln">
</span><span class="tag">&lt;/Store&gt;</span></pre>

<p>
	في المثال التالي، تُخصِص السمة <code>XmlElement</code> اسمًا للخاصية المُزخَرفة بدلًا من اسمها الأصلي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_35" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">XmlElement</span><span class="pun">(</span><span class="typ">ElementName</span><span class="pun">=</span><span class="str">"Dog"</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="typ">Cat</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_7128_37" style="">
<span class="tag">&lt;Foo&gt;</span><span class="pln">
    </span><span class="tag">&lt;Dog/&gt;</span><span class="pln">
</span><span class="tag">&lt;/Foo&gt;</span></pre>

<p>
	في المثال التالي، اُستخدِم جَالْب الخاصية لتحديد صيغة مُخصَّصة للقيمة العائدة بدلًا من الافتراضية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_39" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Dog</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> string _birthStringFormat </span><span class="pun">=</span><span class="pln"> </span><span class="str">"yyyy-MM-dd"</span><span class="pun">;</span><span class="pln">

    </span><span class="pun">[</span><span class="typ">XmlIgnore</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pln"> </span><span class="typ">Birth</span><span class="pln"> </span><span class="pun">{</span><span class="pln">get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;}</span><span class="pln">

    </span><span class="pun">[</span><span class="typ">XmlElement</span><span class="pun">(</span><span class="typ">ElementName</span><span class="pun">=</span><span class="str">"Birth"</span><span class="pun">)]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">BirthString</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        get </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Birth</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">(</span><span class="pln">_birthStringFormat</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">set</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Birth</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">ParseExact</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> _birthStringFormat</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CultureInfo</span><span class="pun">.</span><span class="typ">InvariantCulture</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أخيرًا، تُهمَل الخاصيات المُزخَرفة بالسمة <code>XmlIgnore</code>.
</p>

<h3>
	سلسلة أصناف فرعية بشكل ديناميكي
</h3>

<p>
	<strong>المشكلة</strong>:
</p>

<p>
	أحيانًا قد لا نستطيع استخدَام السِمات (attributes) لإمداد اطار عمل <code>XmlSerializer</code> بكل البيانات الوصفية (metadata) التي يحتاجها لإجراء السَلسَلة.
</p>

<p>
	مثلًا، بفرض أن لدينا صنف أساسي (base class) مطلوب سَلسَلة كائناته. على الرغم من تَوفّر بعض السمات التي قد تُستخدَم للإشارة إلى أنواعه الفرعية، أحيانًا، قد لا تكون جميع الأصناف الفرعية مَعلومَة أثناء تصميم الصنف الأساسي؛ فمن المُحتمل وجود فريق آخر يَعمَل على تطوير بَعضًا من تلك الأنواع الفرعية. كما أنها حتى وإن تَوفَّرت فمِن المُفترض ألا يعلم الصنف الأساسي شيئًا عن أصنافه الفرعية.
</p>

<p>
	<strong>حَل مُقْترَح</strong>:
</p>

<p>
	نحتاج لإمداد المُسَلسِلات (serializers) بالأنواع المَعلومَة بطريقة أُخْرى، مثلًا، باستخدَام بَصمَة أُخْرى من باني الكائنات <code>XmlSerializer(type, knownTypes)‎</code>. تَستقبِل هذه البَصمة مصفوفة تحتوي على الأنواع المَعلومَة كمُعامِل ثان. قد تَفي هذه الطريقة بالغرض ولكنها بتعقيد زمني O(N^2)‎ على الأقل -إذا كان لدينا عدد N من المُسَلسِلات-، فقط لاكتشاف جميع الأنواع المُمرَّرة للمُعامِل.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_41" style="">
<span class="pln">var allSerializers </span><span class="pun">=</span><span class="pln"> allTypes</span><span class="pun">.</span><span class="typ">Select</span><span class="pun">(</span><span class="pln">t </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">XmlSerializer</span><span class="pun">(</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> allTypes</span><span class="pun">));</span><span class="pln">

var serializerDictionary </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> allTypes</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">ToDictionary</span><span class="pun">(</span><span class="pln">i </span><span class="pun">=&gt;</span><span class="pln"> allTypes</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> i </span><span class="pun">=&gt;</span><span class="pln"> allSerializers</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span></pre>

<p>
	لاحظ أنه في المثال بالأعلى، لا علم للصنف الأساسي بالأصناف المشتقة منه، وهو ما يُعدّ أمرًا عاديًا -بل ومطلوبًا- بالبرمجة كائنية التوجه <code><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></code>.
</p>

<p>
	حل أكثر كفاءة:
</p>

<p>
	هناك لحسن الحظ طريقة تَعني بحل هذه المشكلة حلًا أكثر كفاءة عن طريق تَوفير مصفوفة بالأصناف المَعلومَة لعِدة مُسَلسِلات (serializers). تَستخدِم هذه الطريقة التابع <a href="https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.fromtypes(v=vs.110).aspx#Anchor_1" rel="external nofollow">FromTypes(Type[])</a><code>‎</code>، والذي يَسمَح بإنشاء مصفوفة من المُسَلسِلات من النوع <code>XmlSerializer</code> لمُعالجة مصفوفة من الأنواع (Type objects) بكفاءة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_43" style="">
<span class="pln">var allSerializers </span><span class="pun">=</span><span class="pln"> </span><span class="typ">XmlSerializer</span><span class="pun">.</span><span class="typ">FromTypes</span><span class="pun">(</span><span class="pln">allTypes</span><span class="pun">);</span><span class="pln">

var serializerDictionary </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> allTypes</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">ToDictionary</span><span class="pun">(</span><span class="pln">i </span><span class="pun">=&gt;</span><span class="pln"> allTypes</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> i </span><span class="pun">=&gt;</span><span class="pln"> allSerializers</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span></pre>

<p>
	بفرض وجود الأصناف التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_45" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Container</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">JustSomePropInBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">JustSomePropInDerived</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نُنشئ كائن من النوع <code>Container</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_47" style="">
<span class="pln">var sampleObject </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Container</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">()</span><span class="pln"> </span><span class="pun">};</span></pre>

<p>
	نحاول أولًا سَلسَلته دون إمداد المُسَلسِل (serializer) بمعلومات عن النوع <code>Derived</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_49" style="">
<span class="pln">var allTypes </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Container</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Base</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Derived</span><span class="pun">)</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">SetupSerializers</span><span class="pun">(</span><span class="pln">allTypes</span><span class="pun">.</span><span class="typ">Except</span><span class="pun">(</span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Derived</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}).</span><span class="typ">ToArray</span><span class="pun">());</span><span class="pln">
</span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">sampleObject</span><span class="pun">);</span></pre>

<p>
	سيُنتَج عن ذلك رسالة خطأ. نحاول مُجددًا سَلسَلته مع إمداد المُسَلسِل بجميع الأنواع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_51" style="">
<span class="pln">var allTypes </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Container</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Base</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Derived</span><span class="pun">)</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">SetupSerializers</span><span class="pun">(</span><span class="pln">allTypes</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">sampleObject</span><span class="pun">);</span></pre>

<p>
	ستتم العملية بنجاح.
</p>

<p>
	الشيفرة بالكامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7128_53" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Collections</span><span class="pun">.</span><span class="typ">Generic</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Xml</span><span class="pun">.</span><span class="typ">Serialization</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Linq</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Linq</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Container</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">JustSomePropInBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">JustSomePropInDerived</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var sampleObject </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Container</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">()</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
        var allTypes </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Container</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Base</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Derived</span><span class="pun">)</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Trying to serialize without a derived class metadata:"</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">SetupSerializers</span><span class="pun">(</span><span class="pln">allTypes</span><span class="pun">.</span><span class="typ">Except</span><span class="pun">(</span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">Derived</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}).</span><span class="typ">ToArray</span><span class="pun">());</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">sampleObject</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">InvalidOperationException</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"This error was anticipated,"</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"we have not supplied a derived class."</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Now trying to serialize with all of the type information:"</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">SetupSerializers</span><span class="pun">(</span><span class="pln">allTypes</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Serialize</span><span class="pun">(</span><span class="pln">sampleObject</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">();</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Slides down well this time!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Serialize</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="pln">T o</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        serializerDictionary</span><span class="pun">[</span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">)].</span><span class="typ">Serialize</span><span class="pun">(</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Out</span><span class="pun">,</span><span class="pln"> o</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Dictionary</span><span class="pun">&lt;</span><span class="typ">Type</span><span class="pun">,</span><span class="pln"> </span><span class="typ">XmlSerializer</span><span class="pun">&gt;</span><span class="pln"> serializerDictionary</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SetupSerializers</span><span class="pun">(</span><span class="typ">Type</span><span class="pun">[]</span><span class="pln"> allTypes</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var allSerializers </span><span class="pun">=</span><span class="pln"> </span><span class="typ">XmlSerializer</span><span class="pun">.</span><span class="typ">FromTypes</span><span class="pun">(</span><span class="pln">allTypes</span><span class="pun">);</span><span class="pln">
        serializerDictionary </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> allTypes</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">.</span><span class="typ">ToDictionary</span><span class="pun">(</span><span class="pln">i </span><span class="pun">=&gt;</span><span class="pln"> allTypes</span><span class="pun">[</span><span class="pln">i</span><span class="pun">],</span><span class="pln"> i </span><span class="pun">=&gt;</span><span class="pln"> allSerializers</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخْرج:
</p>

<pre class="ipsCode">
Trying to serialize without a derived class metadata:
&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;Container xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
This error was anticipated,
we have not supplied a derived class.
System.InvalidOperationException: There was an error generating the XML document. ---&gt; System.InvalidOperationException: The type Program+Derived was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write2_Base(String n, String ns, Base o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write3_Container(String n, String ns, Container o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write4_Container(Object o)
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle)
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces)
   at Program.Serialize[T](T o)
   at Program.Main()
Now trying to serialize with all of the type information:
&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;Container xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
  &lt;Base xsi:type="Derived"&gt;
    &lt;JustSomePropInBase&gt;0&lt;/JustSomePropInBase&gt;
    &lt;JustSomePropInDerived&gt;0&lt;/JustSomePropInDerived&gt;
  &lt;/Base&gt;
&lt;/Container&gt;
Slides down well this time!
</pre>

<p>
	تقترح رسالة الخطأ الآتي:
</p>

<p>
	"اِستخدِم السمة <code>XmlInclude</code> أو السمة <code>SoapInclude</code> لتخصيص الأنواع غير المَعلومَة بشكل ثابت (statically)"
</p>

<p>
	في الواقع، لا تستطيع دائمًا القيام بذلك -كما أشرنا من قبل-، وحتى إن كان ذلك مُمكنا، لا يُنصح بالقيام بذلك؛ لأن ليس من المُفترَض أن يعلم الصنف الأساسي شيئًا عن الأصناف المُشتقة منه فضلًا عن الإشارة إليها.
</p>

<p>
	هذه هي الطريقة التي يَظهر بها النوع المُشتق بملف XML:
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_7128_55" style="">
<span class="tag">&lt;Base</span><span class="pln"> </span><span class="atn">xsi:type</span><span class="pun">=</span><span class="atv">"Derived"</span><span class="tag">&gt;</span></pre>

<p>
	في المثال بالأعلى، تُشير كلمة <code>Base</code> إلى النوع المُصرَّح عنه للخاصية داخل الصنف <code>Container</code>، بينما كلمة <code>Derived</code> فهي تُشير إلى نوع النسخة المُسْنَدة للخاصية. (إليك <a href="https://dotnetfiddle.net/hufepI" rel="external nofollow">مثال حي</a>)
</p>

<p>
	ترجمة -وبتصرف- للفصل Serialization من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">996</guid><pubDate>Thu, 17 Sep 2020 09:11:28 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62F;&#x64A;&#x646;&#x627;&#x645;&#x64A;&#x643;&#x64A;&#x629; Dynamicity &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%AF%D9%8A%D9%86%D8%A7%D9%85%D9%8A%D9%83%D9%8A%D8%A9-dynamicity-%D9%81%D9%8A-dot-net-r987/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/17.png.af71a4393e4b0ef8eb75da369109022a.png" /></p>

<h2>
	التجميعات (Assemblies)
</h2>

<p>
	تُصرَّف (compile) الأصناف التي تُعرِّفها، مَصحُوبة بتوابعها وخواصها وملفات البايتكود (bytecode) الخاصة بها، وتُحزَّم بداخل تجميعة (Assembly) تكون في صورة ملف يتضمن شيفرة مُصرَّفة جزئيًا بامتداد <code>‎.dll</code> او <code>‎.exe</code>. هذه التجميعات (Assemblies) هي المُكوِّن الأساسي لأي برنامج يتم تشغيله من خلال <a href="https://en.wikipedia.org/wiki/Common_Language_Runtime" rel="external nofollow">بيئة التنفيذ المشتركة (CLR)</a>.
</p>

<p>
	تُعدّ التجميعات ذاتية التَوْثيق، فهي لا تَحتوِي على اﻷنواع وتوابعها وملفات اللغة الوسيطة (IL code) الخاصة بها فقط، بل أيضًا تَضُمّ البيانات الوَصفيّة (metadata) الضرورية للفَحْص والاستهلاك خلال زمني التَصرِّيف (compile time) والتشغيل (runtime).
</p>

<p>
	تَملُك كل تجميعة (Assembly) اسم يَصِف هويتها المتفردة توصيفًا كاملًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_7" style="">
<span class="com">// Will print: "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"</span></pre>

<p>
	تُعدّ أسماء التجميعات التي تحتوي على <code>PublicKeyToken</code> أسماء صارمة (strong).
</p>

<p>
	لِمَنح تجميعة اسمًا صارمًا (strong-naming)، لابّد أن يكون لديك زوجًا من المفاتيح، أحدهما عام (public key) والآخر سري (private key). يُوزَّع المفتاح العام مع التجميعة أما المفتاح السري فيُستخدَم لانشاء بصمة (signature) تُضاف لبيان التجميعة (Assembly manifest)، والذي يحتوي على أسماء جميع ملفات التجميعة وقيمها المقطّعة (hashes)، كما تُصبِح قيمة <code>PublicKeyToken</code> جزءًا من اسمها.
</p>

<p>
	التجميعات التي تَملُك نفس الاسم الصارم هي بالضرورة مُتطابقة، ومِنْ ثَمَّ يُمكِن الاعتماد على ذلك لتَجنُب تضارب أسماء التجميعات (assembly conflicts) وكذلك للإصدارة (versioning).
</p>

<h3>
	تنشئة تجميعة (assembly) ديناميكيًا
</h3>

<p>
	يُوفِّر إطار عمل <code>‎.NET</code> عددًا من الأصناف والتوابع بفضاء الاسم <code>System.Reflection.Emit</code>، والتي يُمكِن اِستخدَامِها لإنشاء تجميعة (assembly) بشكل ديناميكي. عامةً، تَضمّ أي تجميعة (assembly) وَحدة (module) واحدة أو أكثر، كلًا منها قد يتَضمَن صنف واحد أو أكثر.
</p>

<p>
	مثلًا، يَتوفَّر التابع <code>ModuleBuilder.DefineType</code> الذي يُمكِن اِستخدَامه لإضافة نوع جديد، ويُعيد قيمة من النوع <code>TypeBuilder</code>. يُوفِّر هذا النوع بدوره العديد من التوابع لإضافة أعضاء (members) بالنوع المُنشَئ. فمثلًا، يُستخدَم التابع <code>TypeBuilder.DefineField</code> لإضافة حَقْل، بينما يُستخدَم التابع <code>TypeBuilder.DefineProperty</code> لإضافة خاصية. يَتوفَّر أيضًا التابعين <code>TypeBuilder.DefineMethod</code> و <code>TypeBuilder.DefineConstructor</code> لإضافة التوابع وبواني الكائن على الترتيب.
</p>

<p>
	في المثال التالي، نَستعرِض طريقة تَنشئة تجميعة تَضُمّ وَحدة (module) وَاحدة تَشتمِل على تَعرِيف لنوع واحد يَحمِل الاسم <code>MyDynamicType</code>. يتكون هذا النوع من:
</p>

<ul>
<li>
		حَقْل وحيد يُسمَى <code>m_number</code> من النوع العددي <code>int</code>.
	</li>
	<li>
		خاصية مُناظِرة لهذا الحقل تَحمِل الاسم <code>Number</code> لها ضَابِط (setter) وجَالِب (getter).
	</li>
	<li>
		بانيين للكائن (constructor) أحدهما بدون مُعامِلات والآخر يَستقبِل مُعامِل وحيد لتهيئة قيمة الحَقْل المبدئية.
	</li>
	<li>
		التابع <code>MyMethod</code> والذي يَستقبِل مُعامِل من النوع العددي <code>int</code>، ويُعيد حاصل ضرب قيمة المُعامِل في قيمة الحَقْل <code>m_number</code>.
	</li>
</ul>
<p>
	وبالتالي، يَكُون النوع المُراد إنشائه كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_9" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyDynamicType</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> m_number</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">MyDynamicType</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">MyDynamicType</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> initNumber</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        m_number </span><span class="pun">=</span><span class="pln"> initNumber</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Number</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        get </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> m_number</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">set</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> m_number </span><span class="pun">=</span><span class="pln"> value</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">MyMethod</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> multiplier</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> m_number </span><span class="pun">*</span><span class="pln"> multiplier</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سنحتاج أولًا لاستدعاء التابعين <code>DefineDynamicAssembly</code> و <code>DefineDynamicModule</code> لتنشئة كائنين من النوع <code>AssemblyBuilder</code> و <code>ModuleBuilder</code> على الترتيب، يُمثل هذين التابعين كُلًا من التجميعة (assembly) والوَحدة (module) المُراد إنشائها، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_11" style="">
<span class="typ">AssemblyName</span><span class="pln"> aName </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">AssemblyName</span><span class="pun">(</span><span class="str">"DynamicAssemblyExample"</span><span class="pun">);</span><span class="pln">
</span><span class="typ">AssemblyBuilder</span><span class="pln"> ab </span><span class="pun">=</span><span class="pln"> </span><span class="typ">AppDomain</span><span class="pun">.</span><span class="typ">CurrentDomain</span><span class="pun">.</span><span class="typ">DefineDynamicAssembly</span><span class="pun">(</span><span class="pln">
    aName</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">AssemblyBuilderAccess</span><span class="pun">.</span><span class="typ">RunAndSave</span><span class="pln">
</span><span class="pun">);</span><span class="pln">

</span><span class="com">// عادةً ما يكون اسم الوحدة هو نفسه اسم ملف التجميع عند تنشئة ملف تجميع من وحدة واحدة </span><span class="pln">
</span><span class="typ">ModuleBuilder</span><span class="pln"> mb </span><span class="pun">=</span><span class="pln">
    ab</span><span class="pun">.</span><span class="typ">DefineDynamicModule</span><span class="pun">(</span><span class="pln">aName</span><span class="pun">.</span><span class="typ">Name</span><span class="pun">,</span><span class="pln"> aName</span><span class="pun">.</span><span class="typ">Name</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">".dll"</span><span class="pun">);</span></pre>

<p>
	للإعلان عن النوع <code>MyDynamicType</code> داخل الوَحدة المُنشَأة، نَستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_13" style="">
<span class="typ">TypeBuilder</span><span class="pln"> tb </span><span class="pun">=</span><span class="pln"> mb</span><span class="pun">.</span><span class="typ">DefineType</span><span class="pun">(</span><span class="str">"MyDynamicType"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">TypeAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">);</span></pre>

<p>
	لإضافة الحَقْل <code>m_number</code> بالنوع الجديد، نَستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_15" style="">
<span class="typ">FieldBuilder</span><span class="pln"> fbNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineField</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"m_number"</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln">
    </span><span class="typ">FieldAttributes</span><span class="pun">.</span><span class="typ">Private</span><span class="pun">);</span></pre>

<p>
	لإضافة الخاصية <code>Number</code> المُناظِرة للحَقْل، نَستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_17" style="">
<span class="typ">PropertyBuilder</span><span class="pln"> pbNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineProperty</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"Number"</span><span class="pun">,</span><span class="pln"> </span><span class="com">// اسم الخاصية</span><span class="pln">
    </span><span class="typ">PropertyAttributes</span><span class="pun">.</span><span class="typ">None</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln"> </span><span class="com">// نوع الخاصية</span><span class="pln">
    </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span></pre>

<p>
	لإضافة ضَابِط (setter) للخاصية المُنشَئة للتو، نَستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_19" style="">
<span class="typ">MethodBuilder</span><span class="pln"> mbSetNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineMethod</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"set_Number"</span><span class="pun">,</span><span class="pln">
    </span><span class="com">// لعدم السماح باستدعاء الضابط لأنه تابع من نوع خاص</span><span class="pln">
    </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">PrivateScope</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">HideBySig</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">SpecialName</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">typeof</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">),</span><span class="pln"> </span><span class="com">// لا يُعيد الضابط قيمة</span><span class="pln">
    </span><span class="com">// يستقبل الضابط قيمة من النوع العددي</span><span class="pln">
    </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">});</span><span class="pln"> 

</span><span class="com">// ‫سنستخدم مولد الشيفرة الوسيطة IL generator‎ للحصول على متن التابع</span><span class="pln">
il </span><span class="pun">=</span><span class="pln"> mbSetNumber</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">

</span><span class="com">// ‫لابد من تحميل this‎ لأنه المُعامِل الأول لجميع التوابع</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حمل المعامل الثاني الذي يمثل القيمة المراد إسنادها للحقل</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Stfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خزن القيمة الجديدة المحملة للتو بالحقل</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln"> </span><span class="com">// عُد</span><span class="pln">

</span><span class="com">// وأخيرًا، اربط التابع بضابط الخاصية</span><span class="pln">
pbNumber</span><span class="pun">.</span><span class="typ">SetSetMethod</span><span class="pun">(</span><span class="pln">mbSetNumber</span><span class="pun">);</span></pre>

<p>
	عادةً ما يَكُون اسم الضَابِط هو <code>set_Property</code>.
</p>

<p>
	بالمثل، لإضافة جَالِب (getter) لنفس الخاصية، نَستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_21" style="">
<span class="typ">MethodBuilder</span><span class="pln"> mbGetNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineMethod</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"get_Number"</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">PrivateScope</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">HideBySig</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">SpecialName</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln">
    </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">

il </span><span class="pun">=</span><span class="pln"> mbGetNumber</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حمل قيمة الحقل</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln"> </span><span class="com">// أعد القيمة المحملة</span><span class="pln">

</span><span class="com">// وأخيرًا، اربط التابع بجالب الخاصية</span><span class="pln">
pbNumber</span><span class="pun">.</span><span class="typ">SetGetMethod</span><span class="pun">(</span><span class="pln">mbGetNumber</span><span class="pun">);</span></pre>

<p>
	لإضافة بواني الكائن بالنوع الجديد، نَضيِف الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_23" style="">
<span class="typ">ConstructorBuilder</span><span class="pln"> intConstructor </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineConstructor</span><span class="pun">(</span><span class="pln">
    </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">,</span><span class="pln"> 
    </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">Standard</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">HasThis</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

il </span><span class="pun">=</span><span class="pln"> intConstructor</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
</span><span class="com">// ‫حمل this‎</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Call</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">object</span><span class="pun">).</span><span class="typ">GetConstructor</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]));</span><span class="pln"> </span><span class="com">// اِستدعي باني الأب</span><span class="pln">
</span><span class="com">// ‫حمل this‎</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حمل قيمة المعامل الثاني الذي يمثل القيمة الممررة لباني الكائن</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Stfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خزن القيمة المحملة بالحقل</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln">

var parameterlessConstructor </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineConstructor</span><span class="pun">(</span><span class="pln">
    </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">Standard</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">HasThis</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
    </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
il </span><span class="pun">=</span><span class="pln"> parameterlessConstructor</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldc_I4_S</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">byte</span><span class="pun">)</span><span class="lit">42</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حمل القيمة 42</span><span class="pln">
</span><span class="com">// ‫استدعي this(42)‎</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Call</span><span class="pun">,</span><span class="pln"> intConstructor</span><span class="pun">);</span><span class="pln"> 
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span></pre>

<p>
	لاحِظ أنه لابُدّ للبواني من استدعاء باني الصنف الأساسي أو بَانِي آخر بنفس الصنف.
</p>

<p>
	لإضافة التابع <code>MyMethod</code>، نَستخدِم الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_25" style="">
<span class="typ">MethodBuilder</span><span class="pln"> mbMyMethod </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineMethod</span><span class="pun">(</span><span class="pln">
    </span><span class="str">"MyMethod"</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln">
    </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">});</span><span class="pln">

</span><span class="typ">ILGenerator</span><span class="pln"> il </span><span class="pun">=</span><span class="pln"> mbMyMethod</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حمل قيمة الحقل</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// حمل قيمة المعامل الممرر</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Mul</span><span class="pun">);</span><span class="pln"> </span><span class="com">// احسب حاصل ضرب قيمة الحقل بقيمة المعامل</span><span class="pln">
il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln"> </span><span class="com">// عُد</span></pre>

<p>
	وأخيرًا نقوم بالتَنشئِة الفِعلّية للنوع الجديد عن طريق التابع <code>CreateType</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_27" style="">
<span class="typ">Type</span><span class="pln"> ourType </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">CreateType</span><span class="pun">();</span></pre>

<p>
	الشيفرة بالكامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_29" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Reflection</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Reflection</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DemoAssemblyBuilder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">AssemblyName</span><span class="pln"> aName </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">AssemblyName</span><span class="pun">(</span><span class="str">"DynamicAssemblyExample"</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">AssemblyBuilder</span><span class="pln"> ab </span><span class="pun">=</span><span class="pln">
            </span><span class="typ">AppDomain</span><span class="pun">.</span><span class="typ">CurrentDomain</span><span class="pun">.</span><span class="typ">DefineDynamicAssembly</span><span class="pun">(</span><span class="pln">
            aName</span><span class="pun">,</span><span class="pln">
            </span><span class="typ">AssemblyBuilderAccess</span><span class="pun">.</span><span class="typ">RunAndSave</span><span class="pln">
        </span><span class="pun">);</span><span class="pln">

        </span><span class="typ">ModuleBuilder</span><span class="pln"> mb </span><span class="pun">=</span><span class="pln">
            ab</span><span class="pun">.</span><span class="typ">DefineDynamicModule</span><span class="pun">(</span><span class="pln">aName</span><span class="pun">.</span><span class="typ">Name</span><span class="pun">,</span><span class="pln"> aName</span><span class="pun">.</span><span class="typ">Name</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">".dll"</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">TypeBuilder</span><span class="pln"> tb </span><span class="pun">=</span><span class="pln"> mb</span><span class="pun">.</span><span class="typ">DefineType</span><span class="pun">(</span><span class="pln">
            </span><span class="str">"MyDynamicType"</span><span class="pun">,</span><span class="pln">
            </span><span class="typ">TypeAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">FieldBuilder</span><span class="pln"> fbNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineField</span><span class="pun">(</span><span class="pln">
            </span><span class="str">"m_number"</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln">
            </span><span class="typ">FieldAttributes</span><span class="pun">.</span><span class="typ">Private</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">MethodBuilder</span><span class="pln"> mbMyMethod </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineMethod</span><span class="pun">(</span><span class="pln">
            </span><span class="str">"MyMethod"</span><span class="pun">,</span><span class="pln">
            </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln">
            </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
        </span><span class="typ">ILGenerator</span><span class="pln"> il </span><span class="pun">=</span><span class="pln"> mbMyMethod</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln">
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_1</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Mul</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln"> 

        </span><span class="typ">PropertyBuilder</span><span class="pln"> pbNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineProperty</span><span class="pun">(</span><span class="pln">
            </span><span class="str">"Number"</span><span class="pun">,</span><span class="pln"> 
            </span><span class="typ">PropertyAttributes</span><span class="pun">.</span><span class="typ">None</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln"> 

        </span><span class="typ">MethodBuilder</span><span class="pln"> mbSetNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineMethod</span><span class="pun">(</span><span class="pln">
            </span><span class="str">"set_Number"</span><span class="pun">,</span><span class="pln"> 
            </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">PrivateScope</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">HideBySig</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">SpecialName</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">typeof</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">),</span><span class="pln"> 
            </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">});</span><span class="pln"> 
        il </span><span class="pun">=</span><span class="pln"> mbSetNumber</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_1</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Stfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln"> 
        pbNumber</span><span class="pun">.</span><span class="typ">SetSetMethod</span><span class="pun">(</span><span class="pln">mbSetNumber</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">MethodBuilder</span><span class="pln"> mbGetNumber </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineMethod</span><span class="pun">(</span><span class="pln">
            </span><span class="str">"get_Number"</span><span class="pun">,</span><span class="pln">
            </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">PrivateScope</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">HideBySig</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">SpecialName</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">),</span><span class="pln">
            </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
        il </span><span class="pun">=</span><span class="pln"> mbGetNumber</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln"> 
        pbNumber</span><span class="pun">.</span><span class="typ">SetGetMethod</span><span class="pun">(</span><span class="pln">mbGetNumber</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">ConstructorBuilder</span><span class="pln"> intConstructor </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineConstructor</span><span class="pun">(</span><span class="pln">
            </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">,</span><span class="pln"> 
            </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">Standard</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">HasThis</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
        il </span><span class="pun">=</span><span class="pln"> intConstructor</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Call</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">object</span><span class="pun">).</span><span class="typ">GetConstructor</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]));</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_1</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Stfld</span><span class="pun">,</span><span class="pln"> fbNumber</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln">

        var parameterlessConstructor </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">DefineConstructor</span><span class="pun">(</span><span class="pln">
            </span><span class="typ">MethodAttributes</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">Standard</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">CallingConventions</span><span class="pun">.</span><span class="typ">HasThis</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
            </span><span class="typ">Type</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
        il </span><span class="pun">=</span><span class="pln"> parameterlessConstructor</span><span class="pun">.</span><span class="typ">GetILGenerator</span><span class="pun">();</span><span class="pln">
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldarg_0</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ldc_I4_S</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="pln">byte</span><span class="pun">)</span><span class="lit">42</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Call</span><span class="pun">,</span><span class="pln"> intConstructor</span><span class="pun">);</span><span class="pln"> 
        il</span><span class="pun">.</span><span class="typ">Emit</span><span class="pun">(</span><span class="typ">OpCodes</span><span class="pun">.</span><span class="typ">Ret</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Type</span><span class="pln"> ourType </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">CreateType</span><span class="pun">();</span><span class="pln">

        object ourInstance </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Activator</span><span class="pun">.</span><span class="typ">CreateInstance</span><span class="pun">(</span><span class="pln">ourType</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">ourType</span><span class="pun">.</span><span class="typ">GetProperty</span><span class="pun">(</span><span class="str">"Number"</span><span class="pun">)</span><span class="pln">
                          </span><span class="pun">.</span><span class="typ">GetValue</span><span class="pun">(</span><span class="pln">ourInstance</span><span class="pun">));</span><span class="pln">

        ab</span><span class="pun">.</span><span class="typ">Save</span><span class="pun">(@</span><span class="str">"DynamicAssemblyExample.dll"</span><span class="pun">);</span><span class="pln">

        var myDynamicType </span><span class="pun">=</span><span class="pln"> tb</span><span class="pun">.</span><span class="typ">CreateType</span><span class="pun">();</span><span class="pln">
        var myDynamicTypeInstance </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Activator</span><span class="pun">.</span><span class="typ">CreateInstance</span><span class="pun">(</span><span class="pln">myDynamicType</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">myDynamicTypeInstance</span><span class="pun">.</span><span class="typ">GetType</span><span class="pun">());</span><span class="pln"> 

        var numberField </span><span class="pun">=</span><span class="pln"> myDynamicType</span><span class="pun">.</span><span class="typ">GetField</span><span class="pun">(</span><span class="str">"m_number"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">NonPublic</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">Instance</span><span class="pun">);</span><span class="pln">
        numberField</span><span class="pun">.</span><span class="typ">SetValue</span><span class="pln"> </span><span class="pun">(</span><span class="pln">myDynamicTypeInstance</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">numberField</span><span class="pun">.</span><span class="typ">GetValue</span><span class="pun">(</span><span class="pln">myDynamicTypeInstance</span><span class="pun">));</span><span class="pln"> 
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الانعكاس (Reflection)
</h2>

<p>
	يُوفِّر الانعكاس العديد من الأصناف -منها الصنف <code>Assembly</code>- والذي يَعمَل كمُغلِّف للتجميعة (assemblies). يُمكِن لبعض هذه الأصناف تَوفِير معلومات عن التجميعات المُحمَّلة من خلال البيانات الوَصفيّة (metadata) ببيان تلك التجميعات (Assembly manifest). يُمكِن استخدام بعض الأصناف الأُخرى لتَحمِيل ديناميكي للتجميعات، بل ولإنشاء أنواع جديدة واستدعائها ديناميكيا أثناء وقت التشغيل.
</p>

<h3>
	جَلْب بيانات عن تجميعة باستخدام الانعكاس
</h3>

<p>
	اِستخدِم الشيفرة التالية لجلب كائن <code>Assembly</code> الخاص بصنف معين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_31" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Reflection</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Assembly</span><span class="pln"> assembly </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">GetType</span><span class="pun">().</span><span class="typ">Assembly</span><span class="pun">;</span></pre>

<p>
	اِستخدِم الشيفرة التالية لجَلْب كائن <code>Assembly</code> الخاص بالشيفرة قيد التنفيذ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_33" style="">
<span class="typ">Assembly</span><span class="pln"> assembly </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Assembly</span><span class="pun">.</span><span class="typ">GetExecutingAssembly</span><span class="pun">();</span></pre>

<p>
	يُوفِّر الصنف <code>Assembly</code> التابع <code>GetTypes</code> المُستخدَم لجَلْب قائمة بجميع الأصناف المُعرَّفة ضِمْن التجميعة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_35" style="">
<span class="pln">foreach </span><span class="pun">(</span><span class="pln">var type in assembly</span><span class="pun">.</span><span class="typ">GetTypes</span><span class="pun">())</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">type</span><span class="pun">.</span><span class="typ">FullName</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	موازنة كائنين باستخدام الانعكاس
</h3>

<p>
	في المثال التالي، يُستخَدم الانعكاس لموازنة كائنين. بالتحديد، يُستخدم التابع <code>GetType</code> لجلْب قيمة من الصنف <code>Type</code> تُحدد نوع الكائن، والتي بدورها تُستخدَم لجلْب قائمة بحقول الكائن باستدعاء التابع <code>GetFields</code> من خلالها، ثم يتم موازنة قيم تلك الحقول مع نظيراتها بالكائن الآخر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_37" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Equatable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string field1</span><span class="pun">;</span><span class="pln">


    </span><span class="kwd">public</span><span class="pln"> override </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">Equals</span><span class="pun">(</span><span class="pln">object obj</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ReferenceEquals</span><span class="pun">(</span><span class="pln">null</span><span class="pun">,</span><span class="pln"> obj</span><span class="pun">))</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ReferenceEquals</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> obj</span><span class="pun">))</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">

        var type </span><span class="pun">=</span><span class="pln"> obj</span><span class="pun">.</span><span class="typ">GetType</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">GetType</span><span class="pun">()</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> type</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">

        var fields </span><span class="pun">=</span><span class="pln"> type</span><span class="pun">.</span><span class="typ">GetFields</span><span class="pun">(</span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">Instance</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">NonPublic</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">);</span><span class="pln">
        foreach </span><span class="pun">(</span><span class="pln">var field in fields</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">field</span><span class="pun">.</span><span class="typ">GetValue</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> field</span><span class="pun">.</span><span class="typ">GetValue</span><span class="pun">(</span><span class="pln">obj</span><span class="pun">))</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">


    </span><span class="kwd">public</span><span class="pln"> override </span><span class="typ">int</span><span class="pln"> </span><span class="typ">GetHashCode</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var accumulator </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        var fields </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetType</span><span class="pun">().</span><span class="typ">GetFields</span><span class="pun">(</span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">Instance</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">NonPublic</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">BindingFlags</span><span class="pun">.</span><span class="typ">Public</span><span class="pun">);</span><span class="pln">
        foreach </span><span class="pun">(</span><span class="pln">var field in fields</span><span class="pun">)</span><span class="pln">
            accumulator </span><span class="pun">=</span><span class="pln"> unchecked </span><span class="pun">((</span><span class="pln">accumulator </span><span class="pun">*</span><span class="pln"> </span><span class="lit">937</span><span class="pun">)</span><span class="pln"> </span><span class="pun">^</span><span class="pln"> field</span><span class="pun">.</span><span class="typ">GetValue</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">).</span><span class="typ">GetHashCode</span><span class="pun">());</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> accumulator</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنه بغرض التبسيط، فإن المثال باﻷعلى يُجري موازنة معتمدة على الحقول فقط (يتجاهل الحقول الساكنة [static fields]، والخاصيات [properties]).
</p>

<h3>
	جَلْب سِمة تعداد (enum) باستخدام الانعكاس (وتخزينها بصورة مؤقتة caching)
</h3>

<p>
	تُعدّ السمات (attributes) مفيدة للإشارة إلى بعض البيانات الوَصفيّة (metadata) بالتعدادات (enums).
</p>

<p>
	يُستخدَم عادة التابع <code>GetCustomAttributes</code> لجَلْب قيم تلك السمات والذي قد يكون بطيئًا، لذلك من المهم الاستعانة بالذاكرة المخبئية لتخزين تلك القيم (caching)، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_39" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Dictionary</span><span class="pun">&lt;</span><span class="pln">object</span><span class="pun">,</span><span class="pln"> object</span><span class="pun">&gt;</span><span class="pln"> attributeCache </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Dictionary</span><span class="pun">&lt;</span><span class="pln">object</span><span class="pun">,</span><span class="pln"> object</span><span class="pun">&gt;();</span><span class="pln">


</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> T </span><span class="typ">GetAttribute</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> V</span><span class="pun">&gt;(</span><span class="kwd">this</span><span class="pln"> V value</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">where</span><span class="pln"> T </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Attribute</span><span class="pln">
    </span><span class="kwd">where</span><span class="pln"> V </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        object temp</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// حاول جلب قيمة السمة من الذاكرة المخبئية أولًا</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">attributeCache</span><span class="pun">.</span><span class="typ">TryGetValue</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> out temp</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">T</span><span class="pun">)</span><span class="pln"> temp</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// اجلب النوع</span><span class="pln">
            </span><span class="typ">Type</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> value</span><span class="pun">.</span><span class="typ">GetType</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">FieldInfo</span><span class="pln"> fieldInfo </span><span class="pun">=</span><span class="pln"> type</span><span class="pun">.</span><span class="typ">GetField</span><span class="pun">(</span><span class="pln">value</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">());</span><span class="pln">

            </span><span class="com">// اجلب سمات هذا النوع</span><span class="pln">
            T</span><span class="pun">[]</span><span class="pln"> attribs </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">T</span><span class="pun">[])</span><span class="pln">fieldInfo</span><span class="pun">.</span><span class="typ">GetCustomAttributes</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span><span class="pln">

            </span><span class="com">// أعد أول سمة تجدها</span><span class="pln">
            var result </span><span class="pun">=</span><span class="pln"> attribs</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> attribs</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">

            </span><span class="com">// خزن النتيجة بالذاكرة المخبئية</span><span class="pln">
            attributeCache</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> result</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h3>
	ضَبْط خواص الكائنات باستخدام الانعكاس
</h3>

<p>
	بفرض أن لدينا الصنف التالي <code>Classy</code> الذي يَملك الخاصية <code>Propertua</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_41" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Classy</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">Propertua</span><span class="pln"> </span><span class="pun">{</span><span class="pln">get</span><span class="pun">;</span><span class="pln"> </span><span class="typ">set</span><span class="pun">;}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لضبْط الخاصية <code>Propertua</code> الموجودة بكائن من النوع <code>Classy</code> باستخدام الانعكاس، يمكن استخدام التابع <code>SetValue</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_43" style="">
<span class="pln">var typeOfClassy </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">typeof</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Classy</span><span class="pun">);</span><span class="pln">
var classy </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Classy</span><span class="pun">();</span><span class="pln">
var prop </span><span class="pun">=</span><span class="pln"> typeOfClassy</span><span class="pun">.</span><span class="typ">GetProperty</span><span class="pun">(</span><span class="str">"Propertua"</span><span class="pun">);</span><span class="pln">
prop</span><span class="pun">.</span><span class="typ">SetValue</span><span class="pun">(</span><span class="pln">classy</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Value"</span><span class="pun">);</span></pre>

<h3>
	تنشئة كائن من النوع T باستخدام الانعكاس
</h3>

<p>
	باستخدام باني الكائنات الافتراضي (default constructor):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_45" style="">
<span class="pln">T variable </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Activator</span><span class="pun">.</span><span class="typ">CreateInstance</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">));</span></pre>

<p>
	باستخدام بَانِي ذات معاملات غير محدَّدة النوع (parameterized constructor):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_47" style="">
<span class="pln">T variable </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Activator</span><span class="pun">.</span><span class="typ">CreateInstance</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">),</span><span class="pln"> arg1</span><span class="pun">,</span><span class="pln"> arg2</span><span class="pun">);</span></pre>

<h2>
	الإطار المُدار القابل للتوسيع (MEF)
</h2>

<p>
	الإطار المُدار القَابِل للتوسيع <code>Managed Extensibility Framework - MEF</code> هو مكتبة لإنشاء برامج صغيرة الحجم وقابلة للتوسيع.
</p>

<p>
	عادةً ما تُسجَّل التَبَعيّات (dependencies) داخِل ملفات إعداد بالشيفرة المصدرية (hardcoding). يَترتَب على ذلك أنه لا يُصبِح بالإمكان تَغيير تلك التَبَعيّات إلا عن طريق تعديل الشيفرة وإعادة تَجمِيعها. على العكس من ذلك، يَسمَح الإطار المُدار القابل للتوسيع <code>MEF</code> باكتشاف التَبَعيّات أثناء زمن التشغيل (runtime) ضِمْنِيًّا، واستخدامها دون إعداد مُسبَق.
</p>

<p>
	يَسمَح <code>MEF</code> لعِدة مُكَوِّنات (components) بالتواصل معًا بانسيابية وسهولة. يَستخدِم كل مُكَوِّن سِمات مُعينة (attributes) للإعلان عن تَبَعيّاته وقُدراته، أي ما يَحتاج إلى اِستيراده (imports) وما يقوم بتَصديره (exports)-إن وُجِدَ- على الترتيب. يُعلَّن عن كُلًا من الاستيرادات والتصديرات بصورة مُواصَفَة اِصطلاحيّة (contract). يَنبغي لمُصَدِّر ومُستورِد مُعينين الإعلان عن نفس المُواصَفَة الاصطلاحيّة لعَدِّهما نَظيرين. لاحظ أنه لمّا كانت كل هذه المَعلومات مُتوفِّرة بالبيانات الوصفية (metadata) للمُكَوِّن، أَصبَح مِن المُمكن اكتشافها أثناء زمن التشغيل (runtime).
</p>

<p>
	يُزوِّد مُحرِك <code>MEF</code> المُكَوِّنات باستيراداتها (imports) المُعلَّن عنها اعتمادًا على حَاوِي التركيب (composition container) الذي يَضُمّ كتالوجات (catalogs) تَشتمِل على معلومات عن جميع المُكَوِّنات المُصدَّرة والمُتاحة للتركيب.
</p>

<h3>
	تصدير صنف (Exporting)
</h3>

<p>
	يُمكن لأي مُكَوِّن استخدام السمة <code>ExportAttribute</code> للاعلان عن تَصدير (export). في المثال التالي، صُدِّرَ النوع <code>UserProvider</code> كمُحقِّق للمُواصَفَة الاصطلاحيّة <code>IUserProvider</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_49" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Collections</span><span class="pun">.</span><span class="typ">Generic</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Collections</span><span class="pun">.</span><span class="typ">ObjectModel</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">ComponentModel</span><span class="pun">.</span><span class="typ">Composition</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Demo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">Export</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">IUserProvider</span><span class="pun">))]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> sealed </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserProvider</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IUserProvider</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">ReadOnlyCollection</span><span class="pun">&lt;</span><span class="typ">User</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">GetAllUsers</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">User</span><span class="pun">&gt;</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">User</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="str">"admin"</span><span class="pun">),</span><span class="pln">
                </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">User</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Dennis"</span><span class="pun">),</span><span class="pln">
                </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">User</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Samantha"</span><span class="pun">),</span><span class="pln">
            </span><span class="pun">}.</span><span class="typ">AsReadOnly</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال بالأعلى، يُمكن تَعرِيف الصنف <code>UserProvider</code> بأيّ مكان؛ فالمهم هو تَزْوِيد الكتالوج (<code>ComposablePartCatalogs</code>) -الذي يُنشئه البرنامج- بطريقة يَستطيع مِن خلالها اكتشاف هذا الصنف.
</p>

<h3>
	استيراد صنف (Importing)
</h3>

<p>
	يُمكن لأي مُكَوِّن استخدَام السمة <code>ImportAttribute</code> للاعلان عن استيراد (import) أو تَبَعيّة. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_51" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">ComponentModel</span><span class="pun">.</span><span class="typ">Composition</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Demo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> sealed </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserWriter</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">[</span><span class="typ">Import</span><span class="pun">(</span><span class="kwd">typeof</span><span class="pun">(</span><span class="typ">IUserProvider</span><span class="pun">))]</span><span class="pln">
        </span><span class="kwd">private</span><span class="pln"> </span><span class="typ">IUserProvider</span><span class="pln"> userProvider</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">PrintAllUsers</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            foreach </span><span class="pun">(</span><span class="typ">User</span><span class="pln"> user in </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">userProvider</span><span class="pun">.</span><span class="typ">GetAllUsers</span><span class="pun">())</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">user</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال بالأعلى، يُعلِّن الصنف <code>UserWriter</code> عن استيراد لصنف يُحقِّق المُواصَفَة الاصطلاحيّة <code>IUserProvider</code> كقيمة للحَقْل <code>userProvider</code>. لاحِظ أنه ليس مُهمًا أين تقوم بتَعرِيف الصنف المُناظِر؛ فالمهم هو تَزْوِيد الكتالوج (<code>ComposablePartCatalogs</code>) -الذي يُنشئه البرنامج- بطريقة يستطيع من خلالها اكتشاف هذا الصنف.
</p>

<h3>
	الرَبطْ (مثال بسيط)
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2911_53" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">ComponentModel</span><span class="pun">.</span><span class="typ">Composition</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">ComponentModel</span><span class="pun">.</span><span class="typ">Composition</span><span class="pun">.</span><span class="typ">Hosting</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Demo</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var catalog </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ApplicationCatalog</span><span class="pun">())</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var exportProvider </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CatalogExportProvider</span><span class="pun">(</span><span class="pln">catalog</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var container </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CompositionContainer</span><span class="pun">(</span><span class="pln">exportProvider</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                exportProvider</span><span class="pun">.</span><span class="typ">SourceProvider</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> container</span><span class="pun">;</span><span class="pln">
                </span><span class="typ">UserWriter</span><span class="pln"> writer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">UserWriter</span><span class="pun">();</span><span class="pln">
                </span><span class="com">// at this point, writer's userProvider field is null</span><span class="pln">
                container</span><span class="pun">.</span><span class="typ">ComposeParts</span><span class="pun">(</span><span class="pln">writer</span><span class="pun">);</span><span class="pln">
                </span><span class="com">// now, it should be non-null (or an exception will be thrown).</span><span class="pln">
                writer</span><span class="pun">.</span><span class="typ">PrintAllUsers</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال بالأعلى، تم تَزْوِيد حَاوِي التركيب (composition container) بكتالوج من النوع <code>ApplicationCatalog</code>، والذي يَعتمِد -في بَحْثه عن التَصديرات المُناظِرة- على ملفات التجميعات بامتداد <code>‎.exe</code> و <code>DLL</code> الموجودة بمجلد البرنامج. لذلك طالما تَوَفَّرت السِمة <code>[Export(typeof(IUserProvider))‎]</code> باحدى ملفات التجميعات بالمجلد، ستَنجَح عملية استيراد المُواصَفَة الاصطلاحيّة <code>IUserProvider</code> المُعلَّن عنها بداخل الصنف <code>UserWriter</code>.
</p>

<p>
	تَتوفَّر أنواع أُخرى من الكتالوجات مثل <code>DirectoryCatalog</code>، والتي يُمكِن استخدَامِها كبديل أو كإضافة للنوع <code>ApplicationCatalog</code> لتَوسِيع دائرة البَحْث عن تَصدِيرات مُناظِرة للاستيرادات المطلوبة.
</p>

<p>
	ترجمة -وبتصرف- للفصول Reflection - Managed Extensibility Framework - System.Reflection.Emit namespace من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">987</guid><pubDate>Fri, 04 Sep 2020 09:55:08 +0000</pubDate></item><item><title>&#x627;&#x62E;&#x62A;&#x628;&#x627;&#x631; &#x627;&#x644;&#x648;&#x62D;&#x62F;&#x627;&#x62A; unit testing &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-unit-testing-%D9%81%D9%8A-dot-net-r986/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/16.png.8be69e81be7e12e899d827376bc0630c.png" /></p>

<p>
	يُنصح بتعزيز المشروع الخاص بك بتقنية اختبار الوَحْدَات (unit testing)، حيث يُوفِّر ذلك العديد من المزايا منها:
</p>

<ul>
<li>
		سهولة إضافة خاصيات جديدة مع ضمان استمرارية عمل الشيفرة القديمة بطريقة سليمة.
	</li>
	<li>
		توفير توثيق برمجي لخاصيات المشروع.
	</li>
	<li>
		كتابة شيفرة أفضل من خلال تعزيز اِستخدَام الواجهات.
	</li>
</ul>
<h2>
	نصائح لكتابة اختبار الوحدات
</h2>

<ol>
<li>
		ينبغي أن يتكون اسم الاختبار من ثلاثة أجزاء:
	</li>
</ol>
<ul>
<li>
		اسم التابع تحت الاختبار.
	</li>
	<li>
		وصف للموقف المُراد اختباره.
	</li>
	<li>
		وصف التصرف المُتوقع عند حدوث هذا الموقف.
	</li>
</ul>
<p>
	مثال لاسم سئ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_7" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Test_Single</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var stringCalculator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pun">();</span><span class="pln">

    var actual </span><span class="pun">=</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="str">"0"</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Equal</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> actual</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال لاسم جيد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_9" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_SingleNumber_ReturnsSameNumber</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">//</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="2">
<li>
		يَتكون أي اختبار من ثلاث خطوات:
	</li>
</ol>
<ul>
<li>
		خطوة الإِعداد (arrange): يتم خلالها الإِعداد للاختبار بتجهيز الكائنات والنُسخ المُزيَّفة (mocks) وتوابعها بحيث يقتصِر الاختبار على ما نُريد فَحْصه فقط بمَعزَل عن بقية التَبَعيّات (dependencies) وغيره مما لا يَشمَله الاختبار.
	</li>
	<li>
		خطوة التَّنْفيذ (act): يتم خلالها الاستدعاء الفعلّي للتابع تحت الاختبار.
	</li>
	<li>
		خطوة الفَحْص (assert): يتم خلالها إِجراء الفُحوصات المَطلوبة.
	</li>
</ul>
<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_11" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_EmptyString_ReturnsZero</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Arrange</span><span class="pln">
    var stringCalculator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// Act</span><span class="pln">
    var actual </span><span class="pun">=</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="str">""</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// Assert</span><span class="pln">
    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Equal</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> actual</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="3">
<li>
		تجنب كتابة اختبارات تحتوي على شروط منطقية مثل <code>if</code> و <code>for</code> و <code>while</code> ..إلخ؛ لأن ذلك سيزيد من احتمالية وجود أخطاء برمجية بالاختبار، وهذا آخر ما تود أن يحدث. لابُدّ لاختبارات الوحدة أن تكون خالية تمامًا من الأخطاء حتى تكون محلًا للثقة.
	</li>
</ol>
<p>
	مثال سئ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_13" style="">
<span class="pun">[</span><span class="typ">Fact</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_MultipleNumbers_ReturnsCorrectResults</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var stringCalculator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pun">();</span><span class="pln">
    var expected </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    var testCases </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"0,0,0"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"0,1,2"</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"1,2,3"</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    foreach </span><span class="pun">(</span><span class="pln">var test in testCases</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Equal</span><span class="pun">(</span><span class="pln">expected</span><span class="pun">,</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">test</span><span class="pun">));</span><span class="pln">
        expected </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال أفضل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_15" style="">
<span class="pun">[</span><span class="typ">Theory</span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="typ">InlineData</span><span class="pun">(</span><span class="str">"0,0,0"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)]</span><span class="pln">
</span><span class="pun">[</span><span class="typ">InlineData</span><span class="pun">(</span><span class="str">"0,1,2"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)]</span><span class="pln">
</span><span class="pun">[</span><span class="typ">InlineData</span><span class="pun">(</span><span class="str">"1,2,3"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_MultipleNumbers_ReturnsSumOfNumbers</span><span class="pun">(</span><span class="pln">string input</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> expected</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var stringCalculator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pun">();</span><span class="pln">

    var actual </span><span class="pun">=</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">input</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Equal</span><span class="pun">(</span><span class="pln">expected</span><span class="pun">,</span><span class="pln"> actual</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="4">
<li>
		لابُدّ أن يحتوي كل اختبار على جملة فحص وحيدة. إذا كنت تريد إجراء أكثر من فحص لموقف معين، يُمكنك إنشاء اختبار منفصل لكل جملة فحص، مما سيُعطيك تصور أوضح لسبب فشل الاختبار.
	</li>
</ol>
<p>
	مثال سئ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_17" style="">
<span class="pun">[</span><span class="typ">Fact</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_EdgeCases_ThrowsArgumentExceptions</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Throws</span><span class="pun">&lt;</span><span class="typ">ArgumentException</span><span class="pun">&gt;(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">null</span><span class="pun">));</span><span class="pln">
    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Throws</span><span class="pun">&lt;</span><span class="typ">ArgumentException</span><span class="pun">&gt;(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="str">"a"</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال أفضل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_19" style="">
<span class="pun">[</span><span class="typ">Theory</span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="typ">InlineData</span><span class="pun">(</span><span class="pln">null</span><span class="pun">)]</span><span class="pln">
</span><span class="pun">[</span><span class="typ">InlineData</span><span class="pun">(</span><span class="str">"a"</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_InputNullOrAlphabetic_ThrowsArgumentException</span><span class="pun">(</span><span class="pln">string input</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var stringCalculator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pun">();</span><span class="pln">

    </span><span class="typ">Action</span><span class="pln"> actual </span><span class="pun">=</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">input</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Throws</span><span class="pun">&lt;</span><span class="typ">ArgumentException</span><span class="pun">&gt;(</span><span class="pln">actual</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="5">
<li>
		<p>
			افحص التوابع العامة (public) فقط، وتجنب فحص التوابع الخاصة (private) فهي بالنهاية من المُفترض أن تُنفَّذ أثناء تَّنْفيذ احدى التوابع العامة. علاوة على ذلك فإنها تُعدّ مجرد تفصيلة صغيرة ضمن تَّنفيذ معين (implementation). قد يُغيّر المُبرمج في الواقع من طريقة التنفيذ بدون أن يؤثر على الوظيفة الفعلية الواقعة تحت الاختبار. لذا لا تُقيد اختباراتك على تَّنْفيذ بعينه.
		</p>
	</li>
	<li>
		<p>
			عند الحاجة لتهيئة نفس الكائنات لجميع الاختبارات، استخدم توابع مُساعدة (helper methods) بدلًا من اِستخدَام التابعين <code>setup</code> و <code>teardown</code>. يلجأ الكثير من المُبرمجين إلى اضافة شيفرات التهيئة بهما نظرًا لأنهما يُستدعيان تلقائيا قبل بدء تنفيذ أي اختبار وبعد انتهاء تنفيذه على الترتيب، لكن يؤدي ذلك إلى صعوبة قراءة الاختبار كما قد يؤدي أحيانًا إلى تهيئة كائنات غير مطلوبة لبعض الاختبارات.
		</p>
	</li>
</ol>
<p>
	مثال للطريقة غير السليمة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_21" style="">
<span class="kwd">private</span><span class="pln"> readonly </span><span class="typ">StringCalculator</span><span class="pln"> stringCalculator</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="typ">StringCalculatorTests</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    stringCalculator </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// more tests...</span><span class="pln">

</span><span class="pun">[</span><span class="typ">Fact</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_TwoNumbers_ReturnsSumOfNumbers</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var result </span><span class="pun">=</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="str">"0,1"</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Equal</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> result</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال للطريقة الأفضل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_23" style="">
<span class="pun">[</span><span class="typ">Fact</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Add_TwoNumbers_ReturnsSumOfNumbers</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var stringCalculator </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateDefaultStringCalculator</span><span class="pun">();</span><span class="pln">

    var actual </span><span class="pun">=</span><span class="pln"> stringCalculator</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="str">"0,1"</span><span class="pun">);</span><span class="pln">

    </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">Equal</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> actual</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// more tests...</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pln"> </span><span class="typ">CreateDefaultStringCalculator</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringCalculator</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	إضافة مشروع اختبار الوحدات إلى حل موجود مسبقًا
</h2>

<ul>
<li>
		انقر بزر الفأرة الأيمن على الحل (solution) واختر أَضِف مشروع جديد.
	</li>
	<li>
		اختر نموذج مشروع اختبار الوَحْدَات (Unit Test Project) من جزء الاختبارات.
	</li>
	<li>
		اختر اسم للمكتبة (assembly). مثلًا إذا كان اسم المشروع المُختبَر <code>Foo</code>، فرُبما تَستخدِم الاسم <code>Foo.Tests</code>.
	</li>
	<li>
		أَضِف مَرجِع (reference) المشروع المُختبَر ضِمْن مَراجِع مشروع اختبار الوَحْدَات.
	</li>
</ul>
<h2>
	إضافة تابع بغرض الاختبار
</h2>

<p>
	تَتطلَّب MSTest (بيئة العمل الافتراضية للفَحْص) زَخرفة (decoration) الأصناف بغرض الاختبار (test classes) باستخدام السمة <code>TestClass</code>، وكذلك أن تَكون التوابع بغرض الاختبار (test methods) مُزخرَفة باستخدَام السمة <code>TestMethod</code> وأن تَكون عَلنية (public).
</p>

<p>
	في المثال التالي، يَختبِر التابع <code>Test1</code> كَوْن قيمة المُتغيّر <code>result</code> مُساوِية للقيمة 1.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_25" style="">
<span class="pun">[</span><span class="typ">TestClass</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">FizzBuzzFixture</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">TestMethod</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Test1</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//arrange</span><span class="pln">
        var solver </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FizzBuzzSolver</span><span class="pun">();</span><span class="pln">
        </span><span class="com">//act</span><span class="pln">
        var result </span><span class="pun">=</span><span class="pln"> solver</span><span class="pun">.</span><span class="typ">FizzBuzz</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
        </span><span class="com">//assert</span><span class="pln">
        </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">AreEqual</span><span class="pun">(</span><span class="str">"1"</span><span class="pun">,</span><span class="pln">result</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تتوفَّر الكثير من التوابع لإجراء الفحوصات مثل التابع <code>AreEqual</code> و <code>AreNotEqual</code> و <code>IsTrue</code> وغيرها.
</p>

<p>
	مثال آخر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_27" style="">
<span class="pun">[</span><span class="typ">TestClass</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UnitTest1</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> string </span><span class="typ">Expected</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello World!"</span><span class="pun">;</span><span class="pln">

    </span><span class="pun">[</span><span class="typ">TestMethod</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">TestMethod1</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var sw </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringWriter</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">SetOut</span><span class="pun">(</span><span class="pln">sw</span><span class="pun">);</span><span class="pln">
            </span><span class="typ">HelloWorldCore</span><span class="pun">.</span><span class="typ">Program</span><span class="pun">.</span><span class="typ">Main</span><span class="pun">();</span><span class="pln">

            var result </span><span class="pun">=</span><span class="pln"> sw</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">().</span><span class="typ">Trim</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">AreEqual</span><span class="pun">(</span><span class="typ">Expected</span><span class="pun">,</span><span class="pln"> result</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال آخر باستخدام بيئة عمل <code>NUnit</code> للفَحْص (لاحظ اختلاف السمات المُستخدَمة):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3482_29" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">NUnit</span><span class="pun">.</span><span class="typ">Framework</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">HelloWorldTests</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Tests</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> string </span><span class="typ">Expected</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello World!"</span><span class="pun">;</span><span class="pln">

        </span><span class="pun">[</span><span class="typ">SetUp</span><span class="pun">]</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Setup</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">[</span><span class="typ">Test</span><span class="pun">]</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">TestMethod1</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var sw </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StringWriter</span><span class="pun">())</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">SetOut</span><span class="pun">(</span><span class="pln">sw</span><span class="pun">);</span><span class="pln">
                </span><span class="typ">HelloWorldCore</span><span class="pun">.</span><span class="typ">Program</span><span class="pun">.</span><span class="typ">Main</span><span class="pun">();</span><span class="pln">

                var result </span><span class="pun">=</span><span class="pln"> sw</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">().</span><span class="typ">Trim</span><span class="pun">();</span><span class="pln">
                </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">AreEqual</span><span class="pun">(</span><span class="typ">Expected</span><span class="pun">,</span><span class="pln"> result</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	تشغيل اختبار الوحدات
</h2>

<p>
	افتح نافذة <code>Test Explorer</code> من قائمة <code>Test</code> بفيجوال ستوديو، ثم اُنقر على زر "تشغيل الكل (Run All)" مما سيؤدي إلى بدء تَّنْفيذ جميع الاختبارات.
</p>

<p>
	بعد انتهاء تَّنْفيذ أي اختبار، ستجد علامة بجانب اسمه إما باللون الأخضر أو الأحمر. يُشير اللون الأخضر إلى نجاح الاختبار أما اللون الأحمر فيُشير إلى فشله.
</p>

<h2>
	نتائج حية لاختبار الوحدات (Live Unit Testing)
</h2>

<p>
	يُوفِّر فيجوال ستوديو بدايةً من الإصدار 2017 خاصية عَرْض نتائج اختبار الوَحْدَات بصورة حيّة. يُمكنك تفعيل هذه الخاصية من خلال فتح قائمة <code>Test</code> ثم النقر على زر "اختبار حيّ للوَحْدَات Live Unit Testing" ثم على زر "ابدأ Start" بالقائمة الفرعية.
</p>

<p>
	ستجد -في حالة وجود اختبار مُناظِر- علامة صح أو خطأ إلى جانب كل تابع بنافذة مُحرِّر الشيفرة (code editor) لتُشير إلى نجاح أو فشل الاختبارات الخاصة به، كما أنها تُحدَّث تلقائيًا بينما تقوم بتعديل الشيفرة.
</p>

<p>
	ترجمة -وبتصرف- للفصل Unit Testing من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">986</guid><pubDate>Fri, 04 Sep 2020 09:45:51 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x62F;&#x648;&#x64A;&#x644; Internationalization &#x648;&#x627;&#x644;&#x62A;&#x648;&#x637;&#x64A;&#x646; localization &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%AA%D8%AF%D9%88%D9%8A%D9%84-internationalization-%D9%88%D8%A7%D9%84%D8%AA%D9%88%D8%B7%D9%8A%D9%86-localization-%D9%81%D9%8A-dot-net-r985/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/15.png.93f57b3830d485ac2a330cb5f3f49096.png" /></p>

<p>
	يُوفِّر إطار عمل ‎.NET طرائق مُبسطة لتَدْويِل (Internationalization) وتَوْطِين (localization) مشروعك. التَدْويِل هو بناء مشروعك بطريقة تُسهِل من عملية تَهيئته للعَمَل بلغات مُختلفة دون إجراء تَغْييرات جوهرية عليه. يتم ذلك بفَصْل ملفات الترجمة عن ملفات شيفرة المشروع. في المقابل، فإن التَوْطِين هو عملية تهيئة المشروع ذاتها ليعَمَل مع لغة بعينها من خلال ترجمة النصوص إلى تلك اللغة. يُطلَق مُصطلح العَولمة (Globalization) ليشمل كُلًا من التَدْويِل والتَوْطِين.
</p>

<h2>
	مثال بمشروع ASP.NET MVC
</h2>

<p>
	أولًا: أَضِف حزمة <a href="https://www.nuget.org/packages/I18N/" rel="external nofollow">I18N</a> إلى مشروع الـ MVC الخاص بك.
</p>

<p>
	ثانيًا: أَضِف <code>i18n.LocalizingModule</code> لقسم <code>&lt;httpModules&gt;</code> أو لقسم <code>&lt;modules&gt;</code> بملف <code>web.config</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_2929_7" style="">
<span class="com">&lt;!-- IIS 6 --&gt;</span><span class="pln">
</span><span class="tag">&lt;httpModules&gt;</span><span class="pln">
    </span><span class="tag">&lt;add</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"i18n.LocalizingModule"</span><span class="pln"> 
        </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"i18n.LocalizingModule, i18n"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
</span><span class="tag">&lt;/httpModules&gt;</span><span class="pln">

</span><span class="com">&lt;!-- IIS 7 --&gt;</span><span class="pln">
</span><span class="tag">&lt;system.webServer&gt;</span><span class="pln">
    </span><span class="tag">&lt;modules&gt;</span><span class="pln">
        </span><span class="tag">&lt;add</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"i18n.LocalizingModule"</span><span class="pln"> 
            </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"i18n.LocalizingModule, i18n"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;/modules&gt;</span><span class="pln">
</span><span class="tag">&lt;/system.webServer&gt;</span></pre>

<p>
	ثالثًا: أَضِف مجلد باسم <code>locale</code> للمجلد الرئيسي الخاص بموقعك، ثم انشِئ بداخله مجلد فرعي لكل لغة ترغب بدَعْمها، مثلًا <code>/locale/ar/</code>.
</p>

<p>
	رابعًا: انشِئ ملفًا نصيًا باسم <code>messages.po</code> بداخل كل مجلد من المجلدات الفرعية من الخطوة السابقة.
</p>

<p>
	خامسًا: يُمكِنك كتابة السطور التالية بملف <code>messages.po</code>، فقط بغرض الاختبار:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2929_9" style="">
<span class="com">#: Translation test</span><span class="pln">
msgid </span><span class="str">"Hello, world!"</span><span class="pln">
msgstr </span><span class="str">"أهلًا بالعالم‏!‏"</span></pre>

<p>
	سادسًا: أَضِف مُتحكِمًا (controller) إلى المشروع، يُعيد نصًا ما بغرض تجربة الترجمة. في المثال التالي، يُعيد المُتحكِم القيمة <code>"[[[Hello, world!‎]]]"</code>. لاحظ أنه لابُد للنص الموجود داخل الأقواس الثلاثة أن يتطابق مع قيمة <code>msgid</code> ضِمْن ملف الترجمة <code>‎.po</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2929_11" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Web</span><span class="pun">.</span><span class="typ">Mvc</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> I18nDemo</span><span class="pun">.</span><span class="typ">Controllers</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DefaultController</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">ActionResult</span><span class="pln"> </span><span class="typ">Index</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Content</span><span class="pun">(</span><span class="str">"[[[Hello, world!]]]"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سابعًا: شغِّل المشروع، ثم اِفتَح الرابط المُقابِل للإجراء (action) الذي عَرَّفناه للتو، مثلًًا <code>http://localhost:[yourportnumber]/default</code>. ستُلاحِظ أنه قد تم تَغْيير الرابط تلقائيًا ليَعكِس اللغة الافتراضية الخاصة بك كالتالي <code>http://localhost:[yourportnumber]/en/default</code> -بفرض أن الانجليزية هي اللغة الافتراضية بمُتصفحك.
</p>

<p>
	ثامنًا: إذا استبدلت كلمة <code>ar</code> (أو اللغة التي أَعددت ملف ترجمة خاص بها) بكلمة <code>en</code> الموجودة بالرابط، فستظهر النُسخة المُترجمة من النص.
</p>

<p>
	تاسعًا: إذا غَيّرت إعدادات اللغة بمُتصفحك لتفضِيل لغة أُخرى، ثم فتحت الرابط <code>‎/‎‎default</code> مُجددًا دون تخصيص اللغة، ستجد أنه مثل المرة السابقة قد تم تَغْيير الرابط تلقائيًا ليَعكِس لغتك الافتراضية التي قمت بضَبطِها في الخطوة السابقة، وسيَظهر النص مُترجمًا بتلك اللغة.
</p>

<p>
	عاشرًا: أَضِف مُعالِجَات (handlers) بملف <code>web.config</code> لمنع مُستخدِمي موقعك من فَتح مجلد <code>locale</code>.
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_2929_13" style="">
<span class="com">&lt;!-- IIS 6 --&gt;</span><span class="pln">
</span><span class="tag">&lt;system.web&gt;</span><span class="pln">
    </span><span class="tag">&lt;httpHandlers&gt;</span><span class="pln">
        </span><span class="tag">&lt;add</span><span class="pln"> </span><span class="atn">path</span><span class="pun">=</span><span class="atv">"*"</span><span class="pln"> </span><span class="atn">verb</span><span class="pun">=</span><span class="atv">"*"</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"System.Web.HttpNotFoundHandler"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;/httpHandlers&gt;</span><span class="pln">
</span><span class="tag">&lt;/system.web&gt;</span><span class="pln">

</span><span class="com">&lt;!-- IIS 7 --&gt;</span><span class="pln">
</span><span class="tag">&lt;system.webServer&gt;</span><span class="pln">
    </span><span class="tag">&lt;handlers&gt;</span><span class="pln">
        </span><span class="tag">&lt;remove</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"BlockViewHandler"</span><span class="tag">/&gt;</span><span class="pln">
        </span><span class="tag">&lt;add</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"BlockViewHandler"</span><span class="pln"> 
            </span><span class="atn">path</span><span class="pun">=</span><span class="atv">"*"</span><span class="pln"> 
            </span><span class="atn">verb</span><span class="pun">=</span><span class="atv">"*"</span><span class="pln"> </span><span class="atn">preCondition</span><span class="pun">=</span><span class="atv">"integratedMode"</span><span class="pln">  
            </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"System.Web.HttpNotFoundHandler"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;/handlers&gt;</span><span class="pln">
</span><span class="tag">&lt;/system.webServer&gt;</span></pre>

<p>
	ترجمة -وبتصرف- للفصل Globalization من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">985</guid><pubDate>Fri, 04 Sep 2020 09:37:27 +0000</pubDate></item><item><title>&#x636;&#x628;&#x637; &#x627;&#x644;&#x625;&#x639;&#x62F;&#x627;&#x62F;&#x627;&#x62A; Settings &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%B6%D8%A8%D8%B7-%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D8%A7%D8%AA-settings-%D9%81%D9%8A-dot-net-r984/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/14.png.ed2d84571b6c386756577d6241161906.png" /></p>

<p>
	عادةً ما تُخزَّن إعدادات البرنامج بملف xml. وفي المقابل يُوفِّر إطار عمل ‎.NET أنواع مُجهَّزة لإسترجاع قيم تلك الإعدادت. مثلًا الملف <code>app.config</code>:
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_7706_7" style="">
<span class="pun">&lt;?</span><span class="pln">xml version</span><span class="pun">=</span><span class="str">"1.0"</span><span class="pln"> encoding</span><span class="pun">=</span><span class="str">"utf-8"</span><span class="pun">?&gt;</span><span class="pln">
</span><span class="tag">&lt;configuration&gt;</span><span class="pln">
    </span><span class="tag">&lt;appSettings&gt;</span><span class="pln">
        </span><span class="tag">&lt;add</span><span class="pln"> </span><span class="atn">key</span><span class="pun">=</span><span class="atv">"keyName"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"anything, as a string"</span><span class="tag">/&gt;</span><span class="pln">
        </span><span class="tag">&lt;add</span><span class="pln"> </span><span class="atn">key</span><span class="pun">=</span><span class="atv">"keyNames"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"123"</span><span class="tag">/&gt;</span><span class="pln">
        </span><span class="tag">&lt;add</span><span class="pln"> </span><span class="atn">key</span><span class="pun">=</span><span class="atv">"keyNames"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"234"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;/appSettings&gt;</span><span class="pln">
</span><span class="tag">&lt;/configuration&gt;</span></pre>

<p>
	في حالة كان لديك مُفتاحين يَحمِلان نفس الاسم بقسم <code>appSettings</code> بملف الإعدادات كالمثال السابق، تُسترجَع أخِر قيمة.
</p>

<p>
	في الإصدارات 1.0 و 1.1 من إطار عمل .NET كان <a href="https://msdn.microsoft.com/en-us/library/system.configuration.configurationsettings.aspx" rel="external nofollow">النوع <code>ConfigurationSettings</code></a> هو الطريقة المُتَّبَعة لاسترجاع الإعدادات (settings)، لكنه أصبح مَهجُورًا (deprecated) في الإصدارات الحديثة (2.0 أو أحدث) حيث حَلَّت الأنواع <a href="https://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx" rel="external nofollow"><code>ConfigurationManager</code></a> و <a href="https://msdn.microsoft.com/en-us/library/system.web.configuration.webconfigurationmanager.aspx" rel="external nofollow"><code>WebConfigurationManager</code></a> مَحَلّه.
</p>

<h2>
	استرجاع الاعدادات باستخدام النوع <code>ConfigurationSettings</code>
</h2>

<p>
	لاحظ المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7706_9" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Configuration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Diagnostics</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">ConsoleApplication1</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            string keyValue </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ConfigurationSettings</span><span class="pun">.</span><span class="typ">AppSettings</span><span class="pun">[</span><span class="str">"keyName"</span><span class="pun">];</span><span class="pln">
            </span><span class="typ">Debug</span><span class="pun">.</span><span class="typ">Assert</span><span class="pun">(</span><span class="str">"anything, as a string"</span><span class="pun">.</span><span class="typ">Equals</span><span class="pun">(</span><span class="pln">keyValue</span><span class="pun">));</span><span class="pln">

            string twoKeys </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ConfigurationSettings</span><span class="pun">.</span><span class="typ">AppSettings</span><span class="pun">[</span><span class="str">"keyNames"</span><span class="pun">];</span><span class="pln">
            </span><span class="typ">Debug</span><span class="pun">.</span><span class="typ">Assert</span><span class="pun">(</span><span class="str">"234"</span><span class="pun">.</span><span class="typ">Equals</span><span class="pun">(</span><span class="pln">twoKeys</span><span class="pun">));</span><span class="pln">

            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	استرجاع الإعدادات باستخدام النوع <code>ConfigurationManager</code>
</h2>

<p>
	يُدعِّم النوع <a href="https://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx" rel="external nofollow"><code>ConfigurationManager</code></a> الخاصية <code>AppSettings</code> مما يَسمَح لك بالاستمرار باسترجاع قيم الإعدادات الموجودة بقسم <code>appSettings</code> بملف الإعدادات بنفس طريقة الاصدارات القديمة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7706_11" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Configuration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Diagnostics</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">ConsoleApplication1</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            string keyValue </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ConfigurationManager</span><span class="pun">.</span><span class="typ">AppSettings</span><span class="pun">[</span><span class="str">"keyName"</span><span class="pun">];</span><span class="pln">
            </span><span class="typ">Debug</span><span class="pun">.</span><span class="typ">Assert</span><span class="pun">(</span><span class="str">"anything, as a string"</span><span class="pun">.</span><span class="typ">Equals</span><span class="pun">(</span><span class="pln">keyValue</span><span class="pun">));</span><span class="pln">

            var twoKeys </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ConfigurationManager</span><span class="pun">.</span><span class="typ">AppSettings</span><span class="pun">[</span><span class="str">"keyNames"</span><span class="pun">];</span><span class="pln">
            </span><span class="typ">Debug</span><span class="pun">.</span><span class="typ">Assert</span><span class="pun">(</span><span class="str">"234"</span><span class="pun">.</span><span class="typ">Equals</span><span class="pun">(</span><span class="pln">twoKeys</span><span class="pun">));</span><span class="pln">

            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الإعدادات صارمة النوع باستخدام فيجوال ستوديو
</h2>

<p>
	بدلًا من استخدام قسم <code>appSettings</code> بملف الإعدادات، تُمكِنك بيئة التطوير المتكاملة فيجوال ستوديو (Visual Studio IDE) من إدارة كلًا من إعدادات البرنامج والمُستخدِم بسهولة مع المميزات الإضافية التالية:
</p>

<ul>
<li>
		إعدادات صارمة النوع (strongly typed)، أي يُمكِنك تقييد قيمة الإعدادات بنوع معين بشرط أن يَكون بالإمكان سَلسَلة هذا النوع (serializable).
	</li>
	<li>
		سُهولة فَصْل كلًا من إعدادات البرنامج والمُستخدِم حيث تُخزَّن الأولى بملف إعدادات وحيد <code>web.config</code> في حالة المواقع الالكترونية وتطبيقات الويب، بينما تُخزَّن الثانية بملف <code>user.config</code> بمجلد بيانات المُستخدِمين، والذي يختلف مساره بحسب إصدار نظام التشغيل المُستخدَم. علاوة على ذلك، غُيّرت تسمية الملف <code>app.config</code> إلى <code>assembly.exe.config</code> مع استبدال اسم الملف التَّنْفيذي بكلمة <code>assembly</code>.
	</li>
	<li>
		إمكانية دَمج إعدادات البرنامج من عدة مكتبات أصناف (class libraries) إلى ملف إعدادات وحيد بدون حُدوث تَعارُض بالأسماء (name collisions) عن طريق تخصيص قسم (section) لكل مكتبة أصناف.
	</li>
</ul>
<p>
	تُوفِّر غالبية أنواع المشروعات <a href="https://msdn.microsoft.com/en-us/library/a65txexh.aspx" rel="external nofollow">نافذة الإعدادات (settings)</a> بأداة <a href="https://msdn.microsoft.com/en-us/library/z2f953x9.aspx" rel="external nofollow">تصميم خاصيات المشروع (Project Properties Designer)</a>. تُعدّ هذه النافذة نقطة البداية لإنشاء إعدادات مُخصَّصة لكُلًا من البرنامج والمُستخدِم. تكون هذه النافذة فارغة بشكل مبدئي مع رابط وحيد لإنشاء ملف إعدادات افتراضي.
</p>

<p>
	سيؤدي النقر على هذا الرابط إلى التَغْييرات التالية:
</p>

<ul>
<li>
		<p>
			ظهور شبكة تَحكُم (grid control) بنافذة الإعدادات، والتي ستُمكِنك من إضافة مُدخَلات (entries) الإعداد وتعديلها وحَذفِها.
		</p>
	</li>
	<li>
		<p>
			إنشاء ملف إعدادات (<code>app.config</code> أو <code>web.config</code>) في حالة عدم وجوده.
		</p>
	</li>
	<li>
		<p>
			إضافة عنصر <code>Settings.settings</code> أسفل المجلد الخاص بالخاصيات <code>Properties</code> بنافذة مُستكشِف الحل (Solution Explorer). سيفَتَح النقر عليه نافذة الإعدادات.
		</p>
	</li>
	<li>
		<p>
			إضافة ملف جديد <code>Settings.Designer.__(.cs,.vb,etc.)‎</code> أسفل مجلد الخاصيات <code>Properties</code> بمجلد المشروع. يحتوي هذا الملف على تَعرِيف الصنف <code>Settings</code>. لاحظ أن الشيفرة بهذا الملف مُولَّدة آليًا وبالتالي لا ينبغي تعديلها. مع ذلك لمّا كان هذا الصنف مُعرَّف باستخدَام المُحدِّد الجزئي (partial modifier)، تستطيع تَمديده (extend) وإضافة أعضاء (members) أُخرى له بملف مُنفصل. يُنفِّذ هذا الصنف نمط المتفرّدة (singleton) وتُستخدَم الخاصية <code>Default</code> المُعرَّفة بداخله للولوج للنُسخة المتفرّدة.
		</p>
	</li>
</ul>
<p>
	مع كل مُدخَل إِعداد جديد تُضيفُه إلى نافذة الإعدادات، سيَقُوم فيجوال ستوديو بالتالي:
</p>

<ul>
<li>
		تَخزِين المُدخَل الجديد بقسم (section) إعدادات مُخصَّص بملف الإعدادات. صُمم هذا القسم لكي تتم إدارته بواسطة الصنف <code>Settings</code>.
	</li>
	<li>
		إضافة عضو (member) جديد للصنف <code>Settings</code> من النوع المُختار بنافذة الإعدادات. يُعدّ هذا العضو مُمثِلًا للمُدخَل بلغة الـc#‎، ويُستخدَم لقراءة قيمة الإعداد وتعديلها.
	</li>
</ul>
<h2>
	قراءة الإعدادات صارمة النوع المخزَّنة بملف الاعدادات
</h2>

<p>
	بدءً بصنف <code>Settings</code> جديد وقسم إعدادات مُخصَّص:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="50774" data-unique="vev2vhegn" src="https://academy.hsoub.com/uploads/monthly_2020_09/001Settings_Tab_Window.png.47b8ff60d70598ec64dd0b1fe492e140.png" alt="001Settings_Tab_Window.png"></p>

<p>
	أَضِف مُدخَل إعداد جديد للبرنامج من النوع <code>System.Timespan</code> باسم <code>ExampleTimeout</code>، وأسْنِد إليه قيمة تُساوِي دقيقة واحدة، كالتالي:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="50775" data-unique="yz7oal8hm" src="https://academy.hsoub.com/uploads/monthly_2020_09/002Add_Entries_Using_Grid_Control.png.f9c3ed321adf9b6fa8a524e7b80957fa.png" alt="002Add_Entries_Using_Grid_Control.png"></p>

<p>
	ثم اِحفَظ خاصيات المشروع، والذي يُخزِن بدوره مُدخَلات نافذة الإعدادات، كما يُعيد التوليد الآلي للصنف <code>Settings</code>، ويُحَدِّث ملف إعدادات المشروع.
</p>

<p>
	الآن تَستطيع اِسترجاع قيمة هذا المُدخَل بشيفرة C#‎ من خلال الخاصية <code>Default</code> بالنوع <code>Settings</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7706_13" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Diagnostics</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">ConsoleApplication1</span><span class="pun">.</span><span class="typ">Properties</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">ConsoleApplication1</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">TimeSpan</span><span class="pln"> exampleTimeout </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Settings</span><span class="pun">.</span><span class="typ">Default</span><span class="pun">.</span><span class="typ">ExampleTimeout</span><span class="pun">;</span><span class="pln">
            </span><span class="typ">Debug</span><span class="pun">.</span><span class="typ">Assert</span><span class="pun">(</span><span class="typ">TimeSpan</span><span class="pun">.</span><span class="typ">FromMinutes</span><span class="pun">(</span><span class="lit">1</span><span class="pun">).</span><span class="typ">Equals</span><span class="pun">(</span><span class="pln">exampleTimeout</span><span class="pun">));</span><span class="pln">

            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُمكِنك أيضًا الإطلاع على ملف إعدادات المشروع <code>app.config</code> -المُحدَّث تلقائيًا بواسطة فيجوال ستوديو- لفَحْص كيفية تخزين مُدخَلات إعدادات البرنامج، لتجد التالي:
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_7706_15" style="">
<span class="pun">&lt;?</span><span class="pln">xml version</span><span class="pun">=</span><span class="str">"1.0"</span><span class="pln"> encoding</span><span class="pun">=</span><span class="str">"utf-8"</span><span class="pun">?&gt;</span><span class="pln">
</span><span class="tag">&lt;configuration&gt;</span><span class="pln">

    </span><span class="tag">&lt;configSections&gt;</span><span class="pln">
        </span><span class="tag">&lt;sectionGroup</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"applicationSettings"</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"System.Configuration.ApplicationSettingsGroup,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"</span><span class="pln"> </span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;section</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"ConsoleApplication1.Properties.Settings"</span><span class="pln">
                     </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089"</span><span class="pln"> </span><span class="atn">requirePermission</span><span class="pun">=</span><span class="atv">"false"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
        </span><span class="tag">&lt;/sectionGroup&gt;</span><span class="pln">
    </span><span class="tag">&lt;/configSections&gt;</span><span class="pln">

    </span><span class="tag">&lt;appSettings</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

    </span><span class="tag">&lt;applicationSettings&gt;</span><span class="pln">
        </span><span class="tag">&lt;ConsoleApplication1.Properties.Settings&gt;</span><span class="pln">
            </span><span class="tag">&lt;setting</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"ExampleTimeout"</span><span class="pln"> </span><span class="atn">serializeAs</span><span class="pun">=</span><span class="atv">"String"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;value&gt;</span><span class="pln">00:01:00</span><span class="tag">&lt;/value&gt;</span><span class="pln">
            </span><span class="tag">&lt;/setting&gt;</span><span class="pln">
        </span><span class="tag">&lt;/ConsoleApplication1.Properties.Settings&gt;</span><span class="pln">
    </span><span class="tag">&lt;/applicationSettings&gt;</span><span class="pln">

</span><span class="tag">&lt;/configuration&gt;</span></pre>

<p>
	اِستخدَم فيجوال ستوديو القسم <code>applicationSettings</code> وليس <code>appSettings</code> لإدارة مُدخَلات نافذة الإعدادات. يحتوي القسم الجديد على قسم فرعي مخصَّص وِفقًا لفضاء الاسم (namespace). يَحوِي هذا القسم الفرعي على عنصر <code>setting</code> مُنفَصِل لكل مُدخَل (entry). لا يُخزَّن نوع المُدخَل بملف الإعدادات وإنما يُفْرَض فقط من خلال الصنف <code>Settings</code>.
</p>

<p>
	يُمكِنك أيضًا الإطلاع على ملف الصنف <code>Settings</code> -المُحدَّث تلقائيًا بواسطة فيجوال ستوديو- لفَحْص كيفية اِستخدَام الصنف <code>ConfigurationManager</code> لقراءة القسم الفرعي المُخصَّص بالأعلى، لتجد التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7706_17" style="">
<span class="pun">...</span><span class="pln">
</span><span class="pun">[</span><span class="pln">global</span><span class="pun">::</span><span class="typ">System</span><span class="pun">.</span><span class="typ">Configuration</span><span class="pun">.</span><span class="typ">ApplicationScopedSettingAttribute</span><span class="pun">()]</span><span class="pln">
</span><span class="pun">[</span><span class="pln">global</span><span class="pun">::</span><span class="typ">System</span><span class="pun">.</span><span class="typ">Diagnostics</span><span class="pun">.</span><span class="typ">DebuggerNonUserCodeAttribute</span><span class="pun">()]</span><span class="pln">
</span><span class="pun">[</span><span class="pln">global</span><span class="pun">::</span><span class="typ">System</span><span class="pun">.</span><span class="typ">Configuration</span><span class="pun">.</span><span class="typ">DefaultSettingValueAttribute</span><span class="pun">(</span><span class="str">"00:01:00"</span><span class="pun">)]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> global</span><span class="pun">::</span><span class="typ">System</span><span class="pun">.</span><span class="typ">TimeSpan</span><span class="pln"> </span><span class="typ">ExampleTimeout</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    get </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">((</span><span class="pln">global</span><span class="pun">::</span><span class="typ">System</span><span class="pun">.</span><span class="typ">TimeSpan</span><span class="pun">)(</span><span class="kwd">this</span><span class="pun">[</span><span class="str">"ExampleTimeout"</span><span class="pun">]));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	لاحظ اِستخدَام السمة <code>DefaultSettingValueAttribute</code> لتخزِين القيمة المُحدَّدة للمُدخَل بنافذة الإعدادات بأداة تصميم خاصيات المشروع. تُستخدَم هذه القيمة الافتراضية في حالة لم يكن هناك عنصر مقابل لهذا المُدخَل بملف الإعدادات.
</p>

<p>
	ترجمة -وبتصرف- للفصل Settings من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">984</guid><pubDate>Fri, 04 Sep 2020 09:30:38 +0000</pubDate></item><item><title>&#x627;&#x644;&#x627;&#x62A;&#x635;&#x627;&#x644; &#x628;&#x645;&#x635;&#x627;&#x62F;&#x631; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x639;&#x628;&#x631; ADO.NET &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%A8%D9%85%D8%B5%D8%A7%D8%AF%D8%B1-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%B9%D8%A8%D8%B1-adonet-%D9%81%D9%8A-dot-net-r983/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/13.png.aaf78123f40e647ed30f2e018e883617.png" /></p>

<h2>
	استخدام تقنية ADO.NET
</h2>

<p>
	تَستطيع تطبيقات إطار عمل ‎.NET الاتصال بمصادر البيانات (data sources) المُختلفة، مثل خادم SQL، وأوراكل Oracle، وXML، عن طريق تقنية <a href="https://msdn.microsoft.com/en-us/library/h43ks021(v=vs.110).aspx" rel="external nofollow">ADO.NET</a> -من مايكروسوفت-، وبالتالي يُمكِنها إدخال وجَلْب وتعديل البيانات الموجودة بمصدر البيانات (data source) بمجرد الاتصال به وِفقًا للصلاحيات المتناسبة.
</p>

<p>
	تُوفِّر ADO.NET بِنْيَة معمارية بدون اتصال (connection-less)، وهو ما يُعدّ أسلوبًا آمنًا للتَعامُل مع قواعد البيانات؛ لأن -عن طريقه- لم يُعدّ من الضروري الإبقاء على الاتصال طوال الجلسة (session).
</p>

<h2>
	الممارسات المثلى عند التعامل مع ADO.NET
</h2>

<ul>
<li>
		<p>
			كقاعدة عامة، حَاوِل تَقصِير وقت الاتصال قدر المُسْتَطاع، واغلقه بمجرد انتهاء تَّنْفيذ الإجراء المطلوب إغلاقًا صريحًا، مما يَضمَن عودة الكائن المُستخدَم في الاتصال إلى مَجمع الاتصالات (connection pool)، ويُحسِن من أداء الاتصال الفعلّي بخادم قاعدة البيانات. لاحظ أن أكبر حجم لمَجمع الاتصالات (pool max size) هو 100 بشكل افتراضي. <a href="https://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx" rel="external nofollow">تجمُّع الاتصالات (connection pooling) بخادم SQL</a>
		</p>
	</li>
	<li>
		<p>
			أحِط كل الكائنات المُستخدَمة في الاتصال بقاعدة البيانات (database connections) بكتلة <code>using</code>، مما يَضمَن إغلاقها (dispose) والتخلص منها حتى في حالة التبلِّيغ عن اعتراض. اِطلع على <a href="https://msdn.microsoft.com/en-us/library/yh598w02.aspx" rel="external nofollow">عبارة using (مرجع c#)</a> لمزيد من المعلومات.
		</p>
	</li>
	<li>
		<p>
			اِسترجِع سَلاسِل اتصال قواعد البيانات (connection strings) بالاسم من ملف <code>app.config</code> أو <code>web.config</code> بناءً على نوع التطبيق:
		</p>
	</li>
	<li>
		<p>
			يَتطلَّب إدراج مَرجِع لمكتبة <code>System.configuration</code>.
		</p>
	</li>
	<li>
		<p>
			اِطلع على <a href="https://msdn.microsoft.com/en-us/library/ms254494(v=vs.110).aspx" rel="external nofollow">سلاسل الاتصال وملفات الإعداد</a> لمزيد من المعلومات عن كيفية تنظيم ملف الإعداد.
		</p>
	</li>
	<li>
		<p>
			ضَمِّن أي قيمة دَخْل بمُعامِل (parameter)؛ لأنه:
		</p>
	</li>
	<li>
		<p>
			يُجنّبك هجمات الحقن (<a href="https://en.wikipedia.org/wiki/SQL_injection" rel="external nofollow">SQL Injection</a>).
		</p>
	</li>
	<li>
		<p>
			يُجنّبك الأخطاء في حالة استخدام نص مُتلاعَب به (malformed)، مثل تَضْمِين علامة اقتباس أحادية بداخل النص، والتي تَستخدِمها قاعدة البيانات SQL كمِحرِف تهريب (escaping) أو لبدء سِلسِلة نصية جديدة.
		</p>
	</li>
	<li>
		<p>
			يَسمَح لمُوفِّر قاعدة البيانات (database provider) بإعادة اِستخدَام خطط تَّنْفيذ الاستعلام (query plans) -إن أمكن- مما يُعزز من الكفاءة. (غُير مُدَعَّم من جميع مُوفِّري قواعد البيانات، فقط بعضها).
		</p>
	</li>
	<li>
		<p>
			عند التَعامُل مع مُعامِلات قاعدة البيانات:
		</p>
	</li>
	<li>
		<p>
			يُعدّ عدم تَوافق نوع وحجم مُعامِلات قاعدة البيانات أحد أهم الأخطاء الشائعة والتي تؤدي إلى فَشَل عمليات الإضافة والتَحْديث والجَلْب.
		</p>
	</li>
	<li>
		<p>
			قُم بتسمية مُعامِلات قاعدة البيانات بمُسمَّيات ذات مغزى، بنفس الطريقة التي تُسمِي بها أيّ مُتغيّرات بالشيفرة.
		</p>
	</li>
	<li>
		<p>
			حدِّد نوع العمود (column) بقاعدة البيانات، مما يَضمَن عدم اِستخدَام أنواع المُعامِلات الخاطئة وتَجنُّب أيّ نتائج غيْر مُتوقَّعة.
		</p>
	</li>
	<li>
		<p>
			تَأكَد من صلاحية (validate) قيم المُعامِلات قبل تمريرها إلى الأوامر <code>command</code> (فكما تَعلَم: <a href="https://en.wikipedia.org/wiki/Garbage_in,_garbage_out" rel="external nofollow">مُدخلات خاطئة - مُخرجات خاطئة garbage in, garbage out</a>).
		</p>
	</li>
	<li>
		<p>
			اِستخدِم الأنواع الصحيحة عند إسناد القيم للمُعامِلات. مثلًا إذا كان لديك مُعامِل من النوع <code>DateTime</code>، لا تُسْنِد القيمة المطلوبة كسِلسِلة نصية من النوع <code>string</code>، ولكن اِسندها بحيث تَكون من النوع <code>DateTime</code> أي بعد تحليلها (parsing).
		</p>
	</li>
	<li>
		<p>
			حدِّد <a href="https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.size(v=vs.110).aspx" rel="external nofollow">خاصية <code>size</code></a> للمُعامِلات من النوع <code>string</code>؛ فقد يُعاد اِستخدَام نفس خطة تَّنْفيذ الاستعلام (execution plan) إذا كانت المُعامِلات مُتَوافِقة في النوع والحجم. يُستخدم <code>-1</code> للإشارة إلى <code>MAX</code>.
		</p>
	</li>
	<li>
		<p>
			لا تَستخدِم <a href="https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparametercollection.addwithvalue(v=vs.110).aspx" rel="external nofollow">التابع <code>AddWithValue</code></a>؛ لأنه من السهل جدًا أن تَنسَى تَحديد نوع المُعامِل. اطلع على "<a href="http://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/" rel="external nofollow">هل يمكننا التوقف عن استخدام التابع AddWithValue؟</a>" لمزيد من المعلومات.
		</p>
	</li>
	<li>
		<p>
			عند التَعامُل مع كائنات الاتصال:
		</p>
	</li>
	<li>
		<p>
			اِحرص على تأخير فتح الاتصال قدر المُسْتَطاع، واغلقه بأسرع ما يمكن، بحيث يقتصِر وقت الاتصال على تَّنْفيذ الإجراء المطلوب فقط. يُنصح بذلك عامةً عند التَعامُل مع أي مصدر خارجي.
		</p>
	</li>
	<li>
		<p>
			لا تُشارِك الكائنات المُستخدَمة في الاتصال بأي شكل (مثلًا: لا تَستخدِم <a href="https://wiki.hsoub.com/Design_Patterns/singleton" rel="external">نمط المفرّدة</a> (singleton pattern) بهدف مشاركة نُسخة وحيدة من النوع <code>SqlConnection</code>)، ولكن انشِئ كائن جديد إذا اقتضت الضرورة وتَخلَص (dispose) منه بمجرد انتهائه من تَّنْفيذ المطلوب. وذلك للأسباب التالية:
		</p>

		<ul>
<li>
				يَمتلك معظم مُوفِّري قواعد البيانات مَجمع اتصالات (connection pool)، مما يعني أنه ليس من المُكلِف تنشئة كائن اتصال جديد.
			</li>
			<li>
				يَلْغي أي احتمالية مُستقبلية لحُدوث أخطاء إذا بدأت الشيفرة في التَعامُل مع أكثر من خيط (thread).
			</li>
		</ul>
</li>
</ul>
<h2>
	تنفيذ استعلامات SQL بصيغة أمر Command
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1405_7" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SaveNewEmployee</span><span class="pun">(</span><span class="typ">Employee</span><span class="pln"> newEmployee</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    </span><span class="kwd">using</span><span class="pun">(</span><span class="typ">SqlConnection</span><span class="pln"> con </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlConnection</span><span class="pun">(</span><span class="typ">System</span><span class="pun">.</span><span class="typ">Configuration</span><span class="pun">.</span><span class="typ">ConfigurationManager</span><span class="pun">.</span><span class="typ">ConnectionStrings</span><span class="pun">[</span><span class="str">"MyConnectionName"</span><span class="pun">].</span><span class="typ">ConnectionString</span><span class="pun">))</span><span class="pln"> 
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pun">(</span><span class="typ">SqlCommand</span><span class="pln"> sc </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlCommand</span><span class="pun">(</span><span class="str">"INSERT INTO employee (FirstName, LastName,DateOfBirth /*etc*/) VALUES (@firstName, @lastName, @dateOfBirth /*etc*/)"</span><span class="pun">,</span><span class="pln"> con</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
             </span><span class="com">// (2)   </span><span class="pln">
            sc</span><span class="pun">.</span><span class="typ">Parameters</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlParameter</span><span class="pun">(</span><span class="str">"@firstName"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SqlDbType</span><span class="pun">.</span><span class="typ">VarChar</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">){</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> newEmployee</span><span class="pun">.</span><span class="typ">FirstName</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> </span><span class="pun">(</span><span class="pln">object</span><span class="pun">)</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">DBNull</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">});</span><span class="pln">

            sc</span><span class="pun">.</span><span class="typ">Parameters</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlParameter</span><span class="pun">(</span><span class="str">"@lastName"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SqlDbType</span><span class="pun">.</span><span class="typ">VarChar</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">){</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> newEmployee</span><span class="pun">.</span><span class="typ">LastName</span><span class="pln"> </span><span class="pun">??</span><span class="pln"> </span><span class="pun">(</span><span class="pln">object</span><span class="pun">)</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">DBNull</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">});</span><span class="pln">

            sc</span><span class="pun">.</span><span class="typ">Parameters</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlParameter</span><span class="pun">(</span><span class="str">"@dateOfBirth"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SqlDbType</span><span class="pun">.</span><span class="typ">Date</span><span class="pun">){</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> newEmployee</span><span class="pun">.</span><span class="typ">DateOfBirth</span><span class="pun">});</span><span class="pln">

            </span><span class="com">// (3)</span><span class="pln">
            con</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">();</span><span class="pln">
            sc</span><span class="pun">.</span><span class="typ">ExecuteNonQuery</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	(1): تنشئة كائن الاتصال بقاعدة البيانات ضِمْن كتلة <code>using</code>
</p>

<p>
	(2): تم تَحديد النوع <code>SqlDbType.VarChar</code> والحجم <code>200</code> للمُعامِل <code>firstName</code>
</p>

<p>
	(3): إِرجاء الفَتح الفعلّي للاتصال قَدْرِ الإمكان
</p>

<p>
	ملحوظة 1: اطلع على <a href="https://msdn.microsoft.com/en-us/library/system.data.sqldbtype(v=vs.110).aspx" rel="external nofollow">التعداد SqlDbType</a>
</p>

<p>
	ملحوظة 2: اطلع على <a href="https://dev.mysql.com/doc/dev/connector-net/html/T_MySql_Data_MySqlClient_MySqlDbType.htm" rel="external nofollow">التعداد MySqlDbType</a>
</p>

<h2>
	استخدام واجهات مشتركة لتجريد الأنواع الخاصة بالمورد
</h2>

<p>
	نظرًا لوجود العديد من مصادر البيانات (data sources)، وبالتالي العديد من مُوفِّري قواعد البيانات (database providers)، يُفضَّل الاعتماد على واجهات مُشتَرَكة (common interfaces) لتجريد (abstract) العمليات المُشتَرَكة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1405_9" style="">
<span class="pln">var providerName </span><span class="pun">=</span><span class="pln"> </span><span class="str">"System.Data.SqlClient"</span><span class="pun">;</span><span class="pln"> 
var connectionString </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{your-connection-string}"</span><span class="pun">;</span><span class="pln">

var factory </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DbProviderFactories</span><span class="pun">.</span><span class="typ">GetFactory</span><span class="pun">(</span><span class="pln">providerName</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">using</span><span class="pun">(</span><span class="pln">var connection </span><span class="pun">=</span><span class="pln"> factory</span><span class="pun">.</span><span class="typ">CreateConnection</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//IDbConnection</span><span class="pln">
    connection</span><span class="pun">.</span><span class="typ">ConnectionString</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> connectionString</span><span class="pun">;</span><span class="pln">
    connection</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">using</span><span class="pun">(</span><span class="pln">var command </span><span class="pun">=</span><span class="pln"> connection</span><span class="pun">.</span><span class="typ">CreateCommand</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//IDbCommand</span><span class="pln">
        command</span><span class="pun">.</span><span class="typ">CommandText</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{query}"</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">using</span><span class="pun">(</span><span class="pln">var reader </span><span class="pun">=</span><span class="pln"> command</span><span class="pun">.</span><span class="typ">ExecuteReader</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//IDataReader</span><span class="pln">
            </span><span class="kwd">while</span><span class="pun">(</span><span class="pln">reader</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="pun">...</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصل ADO.NET من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">983</guid><pubDate>Fri, 04 Sep 2020 09:20:31 +0000</pubDate></item><item><title>&#x646;&#x638;&#x627;&#x645; &#x625;&#x62F;&#x627;&#x631;&#x629; &#x627;&#x644;&#x62D;&#x632;&#x645; NuGet &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D9%86%D8%B8%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-nuget-%D9%81%D9%8A-dot-net-r982/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/12.png.d1486ad43c86e78440c1c27577d1cb6e.png" /></p>

<p>
	مُدير الحزم <code>NuGet Package Manager</code> هو إضافة (extension) إلى بيئة التطوير المتكاملة فيجوال ستوديو (Visual Studio IDE).
</p>

<p>
	تَحتَاج إلى تَثْبيته كي تتمكن من إدارة الحزم بمشروعك. يُمكن اِستخدَامه من خلال الطرفية أو من خلال واجهة مُستخدِم رسومية (GUI). يُمكنك الإطلاع على المزيد من خلال التوثيق الرسمي: <a href="https://docs.nuget.org/consume/installing-nuget" rel="external nofollow">تَثْبيت عميل NuGet وتَحْديثه</a>.
</p>

<h2>
	تثبيت مدير الحزم NuGet Package Manager
</h2>

<p>
	تستطيع تَثْبيتُه عن طريق اختيار الإضافات والتحديثات <code>Extensions and Updates</code> بقائمة الأدوات <code>Tools</code> بـفيجوال ستوديو. كالتالي:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="50772" data-unique="p01azagt0" src="https://academy.hsoub.com/uploads/monthly_2020_09/001Extensions_AndUpdates_Dialog.png.33bf833879b00d1f22ab4ebe6b5dcc03.png" alt="001Extensions_AndUpdates_Dialog.png"></p>

<p>
	سيُثبِّت ذلك كلًا من :
</p>

<ul>
<li>
		الواجهة الرسومية: تستطيع الولوج إليها من خلال اختيار <code>Manage NuGet Packages...</code> من القائمة المَعْرُوضة بعد النقر بزر الفأرة الأيمن على مجلد المشروع (أو مجلد مَراجِعه <code>References</code>).
	</li>
	<li>
		أداة الطرفية <code>Package Manager Console</code>: تستطيع الوُلوج إليها من خلال قائمة الأدوات <code>Tools</code> -&gt; مُدير الحزم <code>NuGet Package Manager</code> -&gt; طرفية مُدير الحزم <code>Package Manager Console</code>.
	</li>
</ul>
<p>
	لاحظ أن مُدير الحزم مُضمَّن بجميع إصدارات فيجوال ستوديو بدءً من الإصدار 2012.
</p>

<h2>
	إدارة الحزم باستخدام الواجهة الرسومية (UI)
</h2>

<p>
	انقر بزر الفأرة الأيمن على مُجلد المشروع (أو مُجلد مَراجِعه)، ثم اختر <code>Manage NuGet Packages...‎</code> من القائمة. ستُفتَح نافذة مُدير الحزم كالتالي:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="50773" data-unique="fi0y9rrt5" src="https://academy.hsoub.com/uploads/monthly_2020_09/002Manage_Packages_viaUI.png.4eae27dfe75550c4f873416de79098c5.png" alt="002Manage_Packages_viaUI.png"></p>

<h2>
	إدارة الحزم باستخدام الطرفية (Console)
</h2>

<p>
	انقر على قائمة الأدوات <code>Tools</code> -&gt; مُدير الحزم <code>NuGet Package Manager</code> -&gt; طرفية مُدير الحزم <code>Package Manager Console</code>. ستُفتَح الطرفية بفيجوال ستوديو. <a href="https://docs.nuget.org/consume/package-manager-console-powershell-reference" rel="external nofollow">اطلع على التوثيق الرسمي</a>.
</p>

<h3>
	تَثْبيت الحزم
</h3>

<p>
	تَستطيع اِستخدَام العديد من الأوامر من خلال الطرفية مثل الأمر <code>Install-Package</code>، المسئول عن تَثْبيت حزمة بمشروع، كالتالي:
</p>

<pre class="ipsCode">
PM&gt; Install-Package Elmah
</pre>

<p>
	لاحظ أنه في حالة عدم تحديد المشروع المُراد تَثْبيت الحزمة إليه، فإنها تُثبَّت تلقائيًا بالمشروع المُختَار حاليًا كمشروع افتراضي. في المقابل، تستطيع تَخصيص المشروع المطلوب تَثْبيت الحزمة إليه، كالتالي:
</p>

<pre class="ipsCode">
PM&gt; Install-Package Elmah -ProjectName MyFirstWebsite
</pre>

<p>
	تستطيع أيضًا تخصيص إصدار مُعين من الحزمة، كالتالي:
</p>

<pre class="ipsCode">
PM&gt; Install-Package EntityFramework -Version 6.1.2 
</pre>

<h3>
	تحديث الحزم
</h3>

<p>
	اِستخدِم الأمر <code>Update-Package</code> لتَحْدِيث حزمة مُعينة، كالتالي:
</p>

<pre class="ipsCode">
PM&gt; Update-Package EntityFramework
</pre>

<p>
	لاحظ أنه في حالة عدم تحديد المشروع المُراد تَحْدِيث حزمته، فإن أمر التَحْدِيث سيُنفَّذ على جميع المشروعات، وهو بذلك يختلف عن الوَضْع الافتراضي للأمر <code>Install-Package</code> الذي يُنفِّذ الأمر على المشروع الحالي فقط.
</p>

<p>
	في المقابل، تستطيع تخصيص اسم المشروع صراحةً، كالتالي:
</p>

<pre class="ipsCode">
PM&gt; Update-Package EntityFramework -ProjectName MyFirstWebsite
</pre>

<h3>
	إلغاء تثبيت الحزم
</h3>

<pre class="ipsCode">
PM&gt; Uninstall-Package EntityFramework
</pre>

<p>
	بالمثل، يُمكنك تخصيص مشروع معين، كالتالي:
</p>

<pre class="ipsCode">
PM&gt; Uninstall-Package -ProjectName MyProjectB EntityFramework
</pre>

<p>
	بالمثل، يُمكنك تخصيص إصدار معين، كالتالي:
</p>

<pre class="ipsCode">
PM&gt; uninstall-Package EntityFramework -Version 6.1.2
</pre>

<h3>
	إضافة مصدر حزم مثل <code>MyGet</code> و <code>Klondike</code>
</h3>

<pre class="ipsCode">
nuget sources add -name feedname -source http://sourcefeedurl
</pre>

<p>
	ترجمة -وبتصرف- للفصل Dependency Injection من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">982</guid><pubDate>Fri, 04 Sep 2020 09:12:40 +0000</pubDate></item><item><title>&#x62D;&#x642;&#x646; &#x627;&#x644;&#x62A;&#x628;&#x639;&#x64A;&#x629; Dependency Injection &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%AD%D9%82%D9%86-%D8%A7%D9%84%D8%AA%D8%A8%D8%B9%D9%8A%D8%A9-dependency-injection-%D9%81%D9%8A-dot-net-r981/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/11.png.ffa0e347f5537b567079b79a29d819ea.png" /></p>

<p>
	يعني حَقْن التَبَعيّات (Dependency Injection) بالأساس عملية كتابة الأنواع بطريقة تَمنَع تلك الأنواع من التَحكُم بتَبعيّاتها، هي فقط تُعلِّن عن اعتمادها على تَبَعيّات مُعينة، وفي المقابل تُوفَّر لها تلك التبعيّات فيما يُعرَف بعملية الحَقْن (Injection).
</p>

<p>
	في المثال التالي، تَقتصِر مسؤولية النوع <code>Greeter</code> على عرض رسالة تحيّة. للقيام بذلك، يَعتمِد النوع على تَبَعيّتان (dependencies)، تَمنَحُه الأولى نص رسالة التحية المطلوب إخراجها، بينما تُوفِّر التَبَعيّة الأُخرى الوسيلة المُستخدَمة لإخراج التحية. تَصِف الواجهتين <code>IGreetingProvider</code> و <code>IGreetingWriter</code> هاتين التَبَعيّتين على الترتيب، وتُحقَن (inject) التَبَعيّتين بالنوع.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2383_7" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Greeter</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> readonly </span><span class="typ">IGreetingProvider</span><span class="pln"> _greetingProvider</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> readonly </span><span class="typ">IGreetingWriter</span><span class="pln"> _greetingWriter</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Greeter</span><span class="pun">(</span><span class="typ">IGreetingProvider</span><span class="pln"> greetingProvider</span><span class="pun">,</span><span class="pln"> </span><span class="typ">IGreetingWriter</span><span class="pln"> greetingWriter</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        _greetingProvider </span><span class="pun">=</span><span class="pln"> greetingProvider</span><span class="pun">;</span><span class="pln">
        _greetingWriter </span><span class="pun">=</span><span class="pln"> greetingWriter</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Greet</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var greeting </span><span class="pun">=</span><span class="pln"> _greetingProvider</span><span class="pun">.</span><span class="typ">GetGreeting</span><span class="pun">();</span><span class="pln">
        _greetingWriter</span><span class="pun">.</span><span class="typ">WriteGreeting</span><span class="pun">(</span><span class="pln">greeting</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> interface </span><span class="typ">IGreetingProvider</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    string </span><span class="typ">GetGreeting</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> interface </span><span class="typ">IGreetingWriter</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">WriteGreeting</span><span class="pun">(</span><span class="pln">string greeting</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	على الرغم من اعتماد النوع <code>Greeting</code> على كُلًا من الواجهتين <code>IGreetingProvider</code> و <code>IGreetingWriter</code>، فهو في نفس الوقت غيْر مسؤول عن تَنشئة نُسخ من أيّ منهما، وإنما يُفْترَض أن يَستقبِلهما من خلال باني الكائنات (constructor) خاصته. وبالتالي لابد لأي شيفرة تُنشِئ نسخة من هذا النوع أن تُوفِّر هاتين التَبَعيّتين فيما يُعرَف باسم حَقْن (injecting) التَبعيّات.
</p>

<p>
	في المثال السابق، يُمكن تسميتها أيضًا باسم حَقْن باني الكائنات (constructor injection)؛ نظرًا لأن التَبعيّات تُوفَّر من خلال باني الكائنات.
</p>

<p>
	بعضًا من الأعراف (conventions) الأكثر شيوعًا:
</p>

<ul>
<li>
		يُخزِّن باني الكائنات (constructor) الخاص بنوع ما تَبعيّاته (dependencies) بعد استقبالها في حُقول خاصة (private fields). تُصبِح تلك التَبعيّات مُتوفِّرة لكل التوابع غير الساكنة (non-static) بهذا النوع بُمجرد تنشئة نُسخة منه.
	</li>
	<li>
		تَكون الحُقول الخاصة (private fields) للقراءة فقط، ولا يُمكِن تَغْيير قيمتها بعد ضَبْطِها بواسطة باني الكائنات (constructor)، مما يَعكِس أنه ليس من المَنوط -بل وليس بالإمكان- تَغْيير قيم تلك الحُقول خارج باني الكائنات، كما يَضمَن تَوفُّر التَبَعيّات طوال فترة حياة (lifetime) الكائن.
	</li>
	<li>
		تَكون التَبَعيّات عبارة عن واجهات. ليس هذا ضروريًا وإن كان شائعًا؛ لأنه يُسهِّل من استبدال تَّنْفيذ (implementation) تبعيّة معينة بتَّنْفيذ آخر. بالإضافة إلى أنه يَسمَح باستخدَام نُسخ مزيفة (mocks) من الواجهة لأغراض اختبار الوَحْدَات (unit testing).
	</li>
</ul>
<h2>
	لماذا يسهل حقن التبعيات من اختبار الوحدات؟
</h2>

<p>
	في المثال بالأعلى، يَعتمِد النوع <code>Greeter</code> على تَبَعيّتان من الواجهتين <code>IGreetingProvider</code> و <code>IGreetingWriter</code>.
</p>

<p>
	قد يُعيد التَّنْفيذ (implementation) الفعلّي للواجهة <code>IGreetingProvider</code> السِلسِلة النصية من خلال اِستدعاء <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> أو من خلال قاعدة بيانات. بينما قد يَعرِض التَّنْفيذ الفعلّي للواجهة <code>IGreetingWriter</code> النص على الطرفية (console).
</p>

<p>
	لمّا كان النوع <code>Greeter</code> يَستخدِم حَقْن التَبَعيّة (dependency Injection) لتوفير تَبعيّاته، فمن السهل كتابة اختبار وِحْدَة (unit test) يَحقِن نُسخ مزيفة (mocks) من تلك الواجهات، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2383_9" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TestGreetingProvider</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IGreetingProvider</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> string </span><span class="typ">TestGreeting</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello!"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> string </span><span class="typ">GetGreeting</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">TestGreeting</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TestGreetingWriter</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;string&gt;</span><span class="pun">,</span><span class="pln"> </span><span class="typ">IGreetingWriter</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">WriteGreeting</span><span class="pun">(</span><span class="pln">string greeting</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Add</span><span class="pun">(</span><span class="pln">greeting</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">[</span><span class="typ">TestClass</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">GreeterTests</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">[</span><span class="typ">TestMethod</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Greeter_WritesGreeting</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var greetingProvider </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TestGreetingProvider</span><span class="pun">();</span><span class="pln">
        var greetingWriter </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TestGreetingWriter</span><span class="pun">();</span><span class="pln">
        var greeter </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Greeter</span><span class="pun">(</span><span class="pln">greetingProvider</span><span class="pun">,</span><span class="pln"> greetingWriter</span><span class="pun">);</span><span class="pln">
        greeter</span><span class="pun">.</span><span class="typ">Greet</span><span class="pun">();</span><span class="pln">
        </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">AreEqual</span><span class="pun">(</span><span class="pln">greetingWriter</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="typ">TestGreetingProvider</span><span class="pun">.</span><span class="typ">TestGreeting</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملحوظة: عادةً ما يُستخدَم اطار عمل مثل <a href="http://www.moqthis.com/" rel="external nofollow">Moq</a> لتَنشِئة النُسخ المزيفة (mocks)، لكن في المثال بالأعلى، تم كتابة التَّنْفيذات (implementations) المُزيَّفة للتبسيط.
</p>

<p>
	يَتحقق اختبار الوِحْدَة (unit test) بالأعلى مما إذا كان النوع <code>Greeter</code> يَتسلَم نصوص الرسائل ثم يُخرِجها للطباعة بشكل صحيح، مما يعني أن الطريقة التي تَعمَل بها التَبعيّات <code>IGreetingProvider</code> و <code>IGreetingWriter</code> ليست ذات صلة هنا؛ فكل ما يُختبَر هو فقط طريقة تَفاعُل (interact) هذا النوع مع تَبَعيّاته. تَسمَح كتابة النوع بأسلوب حَقْن التَبَعيّة (dependency injection) بحَقْن تَبَعيّات مُزيَّفة دون تعقيد، وهو ما يُسهِل من كتابة اختبار الوَحْدَات (unit testing).
</p>

<h2>
	لماذا نحتاج حاوي الخدمات (IoC Containers)؟
</h2>

<p>
	كما ذكرنا بالأعلى فحَقْن التَبَعيّات هو أسلوب كتابة للأنواع، وهو بذلك يختلف عن اِستخدَام إطار عمل حَقْن التبعيّات (يُعرَف عادة باسم حَاوِي الخدمات DI container / IoC container) مثل Windsor وAutofac وSimpleInjector وNinject وUnity وغيرها.
</p>

<p>
	تُسهِل تلك الحَاوِيات (containers) من عملية حَقْن التبعيّات. فلنفترِض أن لديك عددًا من الأنواع التي تَستخدِم حَقْن التبعيّات. فمثلًا يَعتمِد واحد منها على واجهات متعددة، وبدورها تَعتمَد بعض الأنواع المُنفِّذة لهذه الواجهات على واجهات أخرى وهكذا. لنقل أيضًا أن بعضًا منها يَعتمِد على قيم بعينها. كذلك يُنفِّذ البعض الآخر الواجهة <code>IDisposable</code> مما يعني ضرورة التخلص منها بعد انتهاء الغرض من وجودها. بهذه الطريقة أصبح كل نوع مَكتوبًا كتابة جيدة وبطريقة تُسهِل من اختباره، ولكن في المقابل، أصبحت عملية إنشاء نُسخة من نوع معين أمرًا بالغ التعقيد.
</p>

<p>
	في المثال التالي، نُنشِئ نُسخة من نوع <code>CustomerService</code> والتي تَمتلك تَبعيّات وتلك التَبعيّات بدورها تَمتلك تَبعيّات أُخرى:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2383_11" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="typ">CustomerData</span><span class="pln"> </span><span class="typ">GetCustomerData</span><span class="pun">(</span><span class="pln">string customerNumber</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var customerApiEndpoint </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ConfigurationManager</span><span class="pun">.</span><span class="typ">AppSettings</span><span class="pun">[</span><span class="str">"customerApi:customerApiEndpoint"</span><span class="pun">];</span><span class="pln">
    var logFilePath </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ConfigurationManager</span><span class="pun">.</span><span class="typ">AppSettings</span><span class="pun">[</span><span class="str">"logwriter:logFilePath"</span><span class="pun">];</span><span class="pln">
    var authConnectionString </span><span class="pun">=</span><span class="pln">
        </span><span class="typ">ConfigurationManager</span><span class="pun">.</span><span class="typ">ConnectionStrings</span><span class="pun">[</span><span class="str">"authorization"</span><span class="pun">].</span><span class="typ">ConnectionString</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pun">(</span><span class="pln">var logWriter </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">LogWriter</span><span class="pun">(</span><span class="pln">logFilePath </span><span class="pun">))</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pun">(</span><span class="pln">var customerApiClient </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CustomerApiClient</span><span class="pun">(</span><span class="pln">customerApiEndpoint</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            var customerService </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CustomerService</span><span class="pun">(</span><span class="pln">
                </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlAuthorizationRepository</span><span class="pun">(</span><span class="pln">authorizationConnectionString</span><span class="pun">,</span><span class="pln"> logWriter</span><span class="pun">),</span><span class="pln">
                </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CustomerDataRepository</span><span class="pun">(</span><span class="pln">customerApiClient</span><span class="pun">,</span><span class="pln"> logWriter</span><span class="pun">),</span><span class="pln">
                logWriter
            </span><span class="pun">);</span><span class="pln">

            </span><span class="com">// All this just to create an instance of CustomerService!</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> customerService</span><span class="pun">.</span><span class="typ">GetCustomerData</span><span class="pun">(</span><span class="pln">string customerNumber</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	رُبما تتساءل لماذا لا نُضمِّن شيفرة البناء بالأعلى بداخل دالة منفصلة، بحيث يَقتصِر دَورِها على إعادة كائن من النوع <code>CustomerService</code>؟
</p>

<p>
	دَعنا نَتفِق أنه ليس من المُفترَض لأي نوع معرفة ما إذا كانت تَبعيّاته تُنفِّذ الواجهة <code>IDisposable</code> أم لا، بل لا يُفترَض لتلك الأنواع التخلص من تلك التَبعيّات في حالة كانت كذلك. وإنما جُل التَعامُل مع تلك التَبعيّات هو اِستخدَامها. ولذلك، إذا كان لدينا دالة <code>GetCustomerService</code> تُعيد كائنًا مُكتمِل البناء من النوع <code>CustomerService</code>، فإننا نَفتَح الباب أمام وجود كائنات يُحتمَل امتلاكها لتَبعيّات تُنفِّذ الواجهة <code>IDisposable</code> دون وجود طريقة للولوج الى تلك التَبعيّات للتخلص منها.
</p>

<p>
	إلى جانب مشكلة صعوبة التخلص من الكائنات المُنفِّذة للواجهة <code>IDisposable</code>، مَن قد يرغب باستدعاء سِلسِلة من بواني الكائنات المُتداخِلة بهذه الطريقة لأيّ سبب كان؟ لاحظ أن المثال بالأعلى يُعدّ مجرد مثال قصير وبسيط. يمكن للأمر أن يزداد سوءً.
</p>

<p>
	ينبغي التأكيد على أن هذا لا يعني بالضرورة أن الأنواع مَكتوبة بطريقة خاطئة، فقد تَكون مكتوبة بشكل مثالي تمامًا كل على حِدى، لكن تَجمِيعهم سويًا هو ما قد يُمثِل تحديًا.
</p>

<p>
	هنا يأتي دور حَاوِيات حَقْن التَبعيّات حيث تَسمَح تلك الحَاوِيات بتخصيص النوع أو القيمة التي يجب اِستخدَامها لاِستيفاء تَبعيّة معينة. تُعرَف هذه العملية باسم تَسجِيل التبعيّات (registering dependencies) أو ضَبْط الحَاوِي (configuring the container). فمثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2383_13" style="">
<span class="pln">var container </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WindsorContainer</span><span class="pun">();</span><span class="pln">
container</span><span class="pun">.</span><span class="typ">Register</span><span class="pun">(</span><span class="pln">
    </span><span class="typ">Component</span><span class="pun">.</span><span class="typ">For</span><span class="pun">&lt;</span><span class="typ">CustomerService</span><span class="pun">&gt;(),</span><span class="pln">

    </span><span class="typ">Component</span><span class="pun">.</span><span class="typ">For</span><span class="pun">&lt;</span><span class="typ">ILogWriter</span><span class="pun">,</span><span class="pln"> </span><span class="typ">LogWriter</span><span class="pun">&gt;()</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">DependsOn</span><span class="pun">(</span><span class="typ">Dependency</span><span class="pun">.</span><span class="typ">OnAppSettingsValue</span><span class="pun">(</span><span class="str">"logFilePath"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"logWriter:logFilePath"</span><span class="pun">)),</span><span class="pln">

    </span><span class="typ">Component</span><span class="pun">.</span><span class="typ">For</span><span class="pun">&lt;</span><span class="typ">IAuthorizationRepository</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SqlAuthorizationRepository</span><span class="pun">&gt;()</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">DependsOn</span><span class="pun">(</span><span class="typ">Dependency</span><span class="pun">.</span><span class="typ">OnValue</span><span class="pun">(</span><span class="pln">
        connectionString</span><span class="pun">,</span><span class="pln"> 
        </span><span class="typ">ConfigurationManager</span><span class="pln">
        </span><span class="pun">.</span><span class="typ">ConnectionStrings</span><span class="pun">[</span><span class="str">"authorization"</span><span class="pun">].</span><span class="typ">ConnectionString</span><span class="pln">
    </span><span class="pun">)),</span><span class="pln">

    </span><span class="typ">Component</span><span class="pun">.</span><span class="typ">For</span><span class="pun">&lt;</span><span class="typ">ICustomerDataProvider</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CustomerApiClient</span><span class="pun">&gt;()</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">DependsOn</span><span class="pun">(</span><span class="typ">Dependency</span><span class="pun">.</span><span class="typ">OnAppSettingsValue</span><span class="pun">(</span><span class="pln">
        </span><span class="str">"apiEndpoint"</span><span class="pun">,</span><span class="pln"> 
        </span><span class="str">"customerApi:customerApiEndpoint"</span><span class="pln">
    </span><span class="pun">))</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	جُل ما تَقوم به الشيفرة بالأعلى هو تَبلّيغ الحَاوِي بالآتي:
</p>

<ul>
<li>
		لاستيفاء طلب تَبعيّة من الواجهة <code>ILogWriter</code>، اِنشِئ نُسخة من النوع <code>LogWriter</code>، واستخدِم القيمة الثابتة <code>logWriter:logFilePath</code> الموجودة بملف الإعدادات <code>AppSettings</code> لتوفير السِلسِلة النصية المطلوبة.
	</li>
	<li>
		لاستيفاء طلب تَبعيّة من الواجهة <code>IAuthorizationRepository</code>، اِنشِئ نُسخة من النوع <code>SqlAuthorizationRepository</code>، واستخدِم القيمة المذكورة بالأعلى من قسم <code>ConnectionStrings</code> لتوفير نص سِلسِلة الاتصال بقاعدة البيانات (connection string).
	</li>
	<li>
		لاستيفاء طلب تَبعيّة من الواجهة <code>ICustomerDataProvider</code>، اِنشِئ نُسخة من النوع <code>CustomerApiClient</code>، واستخدِم القيمة الفلانية الموجودة بملف الإعدادات <code>AppSettings</code> لتوفير السِلسِلة النصية المطلوبة.
	</li>
</ul>
<p>
	الآن، عندما نحتاج تَبعيّة معينة، -وهو ما يُعرَف باسم استيفاء (resolving) التبعيّة-، فمن المُمارسات السيئة أن تَستَوفِي التَبَعيّة مُباشرة من الحَاوِي، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2383_15" style="">
<span class="pln">var customerService </span><span class="pun">=</span><span class="pln"> container</span><span class="pun">.</span><span class="typ">Resolve</span><span class="pun">&lt;</span><span class="typ">CustomerService</span><span class="pun">&gt;();</span><span class="pln">
var data </span><span class="pun">=</span><span class="pln"> customerService</span><span class="pun">.</span><span class="typ">GetCustomerData</span><span class="pun">(</span><span class="pln">customerNumber</span><span class="pun">);</span><span class="pln">
container</span><span class="pun">.</span><span class="typ">Release</span><span class="pun">(</span><span class="pln">customerService</span><span class="pun">);</span></pre>

<p>
	يَعتمد النوع <code>CustomerService</code> على التَبعيّتان <code>IAuthorizationRepository</code> و<code>ICustomerDataProvider</code>. ولمّا كان الحَاوِي يَعلم الأنواع التي ينبغي اِنشاؤها لاستيفاء تلك التَبعيّات، بالإضافة إلى مَعرِفته بالأنواع التي ينبغي إنشاؤها لاستيفاء تَبعيّات تلك التَبعيّات، فإنه يُنشِئ جميع الأنواع المطلوبة إلى النقطة التي يُصبِح فيها قادرًا على إعادة نُسخة من النوع الأساسي المَطلوب <code>CustomerService</code>.
</p>

<p>
	إذا وَجَد الحَاوِي نفسه مُضطرًا لاستيفاء تَبعيّة لم يتم تسجيلها مثل <code>IDoesSomethingElse</code>، فإنه سيُبلِّغ عن اعتراض واضح يُعلِمنا بعدم تَوفُّر المعلومات المطلوبة لاستيفاء تلك الواجهة.
</p>

<p>
	قد تختلف حَاوِيات حَقْن التَبعيّات عن بعضها قليلًا، لكنها توفر لنا بشكل عام قدرًا معينًا من التَحكُم بطريقة إنشاء الأنواع. فمثلًا، هل نرغب بإنشاء نُسخة وحيدة من واجهة معينة ونُوفِّرها لأي نوع يطلبها، أم نرغب بإنشاء نُسخة جديدة من تلك الواجهة في كل مرة تُطلَّب فيها تلك التَبعيّة؟ تُوفر غالبية الحَاوِيات طريقة ما لتخصيص ذلك.
</p>

<p>
	ماذا عن الأنواع المُنفِّذة للواجهة IDisposable؟ في الواقع، استدعينا <code>container.Release(customerService)‎</code> لهذا الغرض. تقوم غالبية الحَاوِيات بالتخلُص (Dispose) من نُسخ التَبعيّات التي تحتاج لذلك.
</p>

<p>
	قد يبدو تسجيل التَبعيّات -كما رأينا بالأعلى- عملًا كثيرًا للقيام به. لكنه حقًا سيُؤْتي ثماره خاصة عند العمل على تطبيق يََحتاج لأنواع كثيرة تَعتمِد بدورها على تَبعيّات أُخرى كثيرة، وأنه لو اضطررنا لكتابة نفس تلك الأنواع بدون اِستخدَام حَقْن التبعيّات، فسيُصبِح من الصعب جدًا التَعامُل مع هذا التطبيق واختباره.
</p>

<p>
	بهذا نكون ألقينا نظرة خاطفة على أسباب اِستخدَام حَاوِيات حَقْن التبعيّات. مع ذلك فإن ضَبْط تطبيق معين بحيث يَستخدِم احدى تلك الحَاوِيات ليس مجرد موضوع واحد، وإنما عدة مواضيع؛ حيث ستختلف التَعلِيمات والأمثلة من حَاوِي لآخر، ولكنه إجراء غير مُعقَّد على الإطلاق.
</p>

<p>
	ترجمة -وبتصرف- للفصل Dependency Injection من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">981</guid><pubDate>Fri, 04 Sep 2020 09:05:17 +0000</pubDate></item><item><title>&#x62A;&#x646;&#x641;&#x64A;&#x630; &#x627;&#x644;&#x645;&#x647;&#x627;&#x645; &#x628;&#x627;&#x644;&#x62A;&#x648;&#x627;&#x632;&#x64A; &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%AA%D9%86%D9%81%D9%8A%D8%B0-%D8%A7%D9%84%D9%85%D9%87%D8%A7%D9%85-%D8%A8%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%B2%D9%8A-%D9%81%D9%8A-dot-net-r980/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_09/10.png.21a98ee87a6c94d5bd9217277187f370.png" /></p>

<p>
	تُسهِل بيئة عمل ‎.NET من البرمجة مُتعددة الأنوية (multi-core programming) من خلال توفير مَكتبة تَوازِي المَهامّ Task Parallel Library، حيث تَسمَح لك المكتبة بكتابة شيفرة -بالإضافة إلى كَوْنها مَقْرُوءة- فهي تُؤقلم نفسها مع العدد المُتاح من الأنوية (cores)، مما يَضمَن الترقية التلقائية للشيفرة وتحسين أدائها مع ترقية البيئة (environment).
</p>

<h2>
	توازي البيانات (Data parallelism)
</h2>

<p>
	تَوازِي البيانات (Data parallelism) هو التَّنفيذ المُتواقِت (concurrent) لنفس ذات العملية على عدة عناصر مُخزَّنة إِمّا بتَجمِيعة أو بمصفوفة. يُوفِّر إطار العمل ‎.NET كلًا من البنائين البرمجيين (constructs) أو بشكل أدق التابعين <code>Parallel.For</code> و <code>Parallel.Foreach</code> لتَّنْفيذ حلقة (loop) مُتواقِتة من خلال تجزئة البيانات إلى مجموعات تُعالَج بنفس ذات الوقت. تُعدّ كلًا منهما النُسخة المُتواقِتة من الحلقة (loop) باستخدام <code>for</code> و <code>foreach</code> على الترتيب. مثلًا انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_7" style="">
<span class="com">// النسخة المتتالية</span><span class="pln">
foreach </span><span class="pun">(</span><span class="pln">var item in sourcecollection</span><span class="pun">){</span><span class="pln">
    </span><span class="typ">Process</span><span class="pun">(</span><span class="pln">item</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// النسخة المتواقتة</span><span class="pln">
</span><span class="typ">Parallel</span><span class="pun">.</span><span class="typ">Foreach</span><span class="pun">(</span><span class="pln">sourcecollection</span><span class="pun">,</span><span class="pln"> item </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Process</span><span class="pun">(</span><span class="pln">item</span><span class="pun">));</span></pre>

<p>
	صُمم التابع <code>Parallel.ForEach</code> بطريقة تَسمَح له -إن أمكن- باِستخدَام أكثر مِن نواة (core) أثناء التَّنْفيذ مما يُحسِن من أداء الشيفرة.
</p>

<h3>
	استخدام التابع <code>Parallel.For</code>
</h3>

<p>
	يُنفِّذ البناء البرمجي أو التابع <code>Parallel.For</code> حلقة (loop) مُتواقِتة.
</p>

<p>
	تتوافر عدة بصمات من هذا التابع تَستقبِل جميعها القيمة الأولية والنهائية للحلقة كأول مُعامِلين. تختلف البصمات بعد ذلك في عدد ونوع المُعامِلات لكن بالأخير لابُدّ لهن جميعًا من اِستقبَال مُفوَّض مَتن الحلقة من النوع <code>Delegate</code>، والذي يَحوِي العبارات البرمجية المطلوب تَّنْفيذها. على سبيل المثال، تَستقبِل البصمة، في المثال التالي، مُفوَّض مَتن الحلقة كمُعامِل رابع. تُمرَّر قيمة الحلقة الحالية (counter) لهذا المُفوَّض كأول مُعامِل له.
</p>

<p>
	ملحوظة: تتوفَّر بصمات مُبسطة من التابع <code>Parallel.For</code> تَقتصِر على المُعامِلات الثلاثة المذكورة بالأعلى والتي تُمثِل الأساس الجوهري لأيّ حلقة (loop) سواء كانت مُتواقِتة أم لا.
</p>

<p>
	يُنشِئ التابع <code>Parallel.For</code> عدة خيوط (threads) تُنفَّذ بنفس ذات الوقت. عادةً ما يحتاج كل خيط (thread) منها لمُتغيّر محلي (local) خاص يَتوَافر طوال فترة حياة (lifetime) الخيط. تَسمَح البصمة في المثال التالي بذلك، حيث يُستخدَم مُعامِلها الثالث لتهيئة القيمة المبدئية لذلك المُتغيّر. يُمرَّر هذا المتغير كمُعامِل ثالث إلى مُفوَّض مَتن الحلقة، بحيث يَستطيع التعديل من قيمته وإعادته لتَستقبِله الحلقة التالية ضِمْن نفس الخيط. تستمر العملية حتى ينتهي تَّنْفيذ جميع الحلقات ضِمْن نفس الخيط، وعندها تُمرَّر القيمة النهائية للمُتغيّر إلى مُفوَّض أخير (Delegate) من النوع <code>Action</code>، والذي يُنفَّذ مرة واحدة فقط قبل انتهاء فترة حياة الخيط. هذا المفوَّض الأخير هو المُعامِل الخامس للبصمة في المثال التالي.
</p>

<p>
	في المثال التالي، يُحسَب مجموع الأعداد من 1 إلى 10000 بصورة مُتواقِتة. بعد انتهاء كل خيط من تَّنْفيذ حلقاته، تُضاف القيمة النهائية للمُتغيّر المحلي الخاص بالخيط <code>localSum</code> إلى القيمة الكلية الفعلّية <code>total</code> باِستخدَام التابع <code>Interlocked.Add</code> وذلك لضَمان الأمن الخيطي (thread-safety).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_9" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Threading</span><span class="pun">;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> total </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Parallel</span><span class="pun">.</span><span class="typ">For</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> 
                 </span><span class="lit">10001</span><span class="pun">,</span><span class="pln">
                 </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="com">// القيمة المبدئية,</span><span class="pln">
                 </span><span class="pun">(</span><span class="pln">num</span><span class="pun">,</span><span class="pln"> state</span><span class="pun">,</span><span class="pln"> localSum</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> num </span><span class="pun">+</span><span class="pln"> localSum</span><span class="pun">,</span><span class="pln">
                 localSum </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Interlocked</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">ref total</span><span class="pun">,</span><span class="pln"> localSum</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> total</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<h3>
	استخدام التابع <code>Parallel.ForEach</code>
</h3>

<p>
	كالمثال السابق، يُنفِّذ التابع <code>Parallel.ForEach</code> حلقة (loop) مُتواقِتة، لكنه يُجريها على تَجمِيعَة بحيث تُقسَّم عناصر التَجمِيعَة وتُوزَّع على الخيوط المُنشئة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_11" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Threading</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> total </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    var numbers </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">).</span><span class="typ">ToList</span><span class="pun">();</span><span class="pln">
    </span><span class="typ">Parallel</span><span class="pun">.</span><span class="typ">ForEach</span><span class="pun">(</span><span class="pln">numbers</span><span class="pun">,</span><span class="pln">
                     </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="com">// القيمة المبدئية</span><span class="pln">
                     </span><span class="pun">(</span><span class="pln">num</span><span class="pun">,</span><span class="pln"> state</span><span class="pun">,</span><span class="pln"> localSum</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> num </span><span class="pun">+</span><span class="pln"> localSum</span><span class="pun">,</span><span class="pln">
                     localSum </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Interlocked</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">ref total</span><span class="pun">,</span><span class="pln"> localSum</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> total</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	تَتوفَّر بصمات أبسط من التابع <code>Parallel.ForEach</code>، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_13" style="">
<span class="typ">Parallel</span><span class="pun">.</span><span class="typ">Foreach</span><span class="pun">(</span><span class="pln">sourcecollection</span><span class="pun">,</span><span class="pln"> item </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Process</span><span class="pun">(</span><span class="pln">item</span><span class="pun">));</span></pre>

<p>
	يتوفَّر التابع <code>Parallel.ForEach</code> بلغة الفيجوال بيسك كالتالي:
</p>

<pre class="ipsCode" id="ips_uid_3759_15">
For Each row As DataRow In FooDataTable.Rows
Me.RowsToProcess.Add(row)
Next

Dim myOptions As ParallelOptions = New ParallelOptions()
myOptions.MaxDegreeOfParallelism = environment.processorcount
Parallel.ForEach(RowsToProcess, myOptions, Sub(currentRow, state)
    ProcessRowParallel(currentRow, state)
End Sub)
</pre>

<h2>
	توازي المهام (Task parallelism)
</h2>

<p>
	تَوازِي المَهامّ (Task parallelism) هو التَّنْفيذ المُتواقِت (concurrent) لعمليات مُنفصلة.
</p>

<p>
	تَعتمِد مكتبة تَوازِي المَهامّ (Task Parallel Library) بشكل رئيسي على مفهوم المَهامّ (tasks)، والتي يُمكن مُوازنتِها بالخيوط (threads) ولكن على مُستوى أعلى من التجريد (abstraction).
</p>

<p>
	تَكون المَهامّ إمّا من النوع <code>Task</code> إذا كانت لا تُعيد قيمة أو من النوع <code>Task&lt;T&gt;‎</code> إذا كانت تُعيد قيمة من النوع T.
</p>

<h3>
	استخدام التابع <code>Parallel.Invoke</code>
</h3>

<p>
	يُعدّ التابع <code>Parallel.Invoke</code> أحد أبسط وسائل تَحقيق تَوازِي المَهامّ، حيث لا يَتطلَّب أي تَعامُل مباشر مع النوع <code>Task</code>. فقط مَرِّر إليه أيّ عدد من العمليات، كلًا منها من النوع <code>Delegate&lt;Action&gt;‎</code>، وسيُحوِّلها إلى عدة مَهامّ (tasks) ثم يُنفِّذها بصورة مُتواقِتة، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_17" style="">
<span class="pln">var actions </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">).</span><span class="typ">Select</span><span class="pun">(</span><span class="pln">
    n </span><span class="pun">=&gt;</span><span class="pln"> 
    </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Action</span><span class="pun">(</span><span class="pln">
        </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"I'm task "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> n</span><span class="pun">);</span><span class="pln">

            </span><span class="kwd">if</span><span class="pun">((</span><span class="pln">n </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
                </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">"Exception from task "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> n</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">)).</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Parallel</span><span class="pun">.</span><span class="typ">Invoke</span><span class="pun">(</span><span class="pln">actions</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">AggregateException</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    foreach</span><span class="pun">(</span><span class="pln">var inner in ex</span><span class="pun">.</span><span class="typ">InnerExceptions</span><span class="pun">)</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task failed: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> inner</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لمزيد من التَحكُم ستحتاج إلى التَعامُل مع النوع <code>Task</code> مباشرة.
</p>

<h3>
	تنشئة مُهِمّة <code>Task</code> باستخدام باني كائنات النوع <code>Task</code>
</h3>

<p>
	يُمكنك إنشاء نُسخة من النوع <code>Task</code> مباشرة باِستخدَام باني الكائنات. فقط مَرِّر مُعامِلًا من النوع <code>Delegate</code> إليه يَحوِي العبارات البرمجية المُراد تَّنْفيذها خلال المُهِمّة. تحتاج لإستدعاء التابع <code>Start</code> اِستدعاءً صريحًا لبدء تَّنْفيذ المُهِمّة. كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_19" style="">
<span class="pln">var task </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task code starting..."</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="lit">2000</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"...task code ending!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Starting task..."</span><span class="pun">);</span><span class="pln">
task</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">
task</span><span class="pun">.</span><span class="typ">Wait</span><span class="pun">();</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task completed!"</span><span class="pun">);</span></pre>

<h3>
	تنشئة مُهِمّة <code>Task</code> باستخدام التابع <code>Task.Run</code>
</h3>

<p>
	بالمثل يَستقبِل التابع <code>Task.Run</code> مُعامِلًا من النوع <code>Delegate</code> يَحوِي العبارات البرمجية المُراد تَّنْفيذها خلال المُهِمّة، وينشئ مُهِمّة <code>Task</code> ويُنفِّذها في آن واحد. لذا، أنت لست في حاجة لاِستدعاء التابع <code>Start</code>.
</p>

<p>
	إذا كان الـ <code>Delegate</code> المُمرَّر من النوع <code>Action</code>، يُنشَئ مُتغيّر من النوع <code>Task</code>. كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_21" style="">
<span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Starting task..."</span><span class="pun">);</span><span class="pln">

var task </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task code starting..."</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="lit">2000</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"...task code ending!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

task</span><span class="pun">.</span><span class="typ">Wait</span><span class="pun">();</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task completed!"</span><span class="pun">);</span></pre>

<h3>
	تنشئة مُهِمّة <code>Task&lt;T&gt;‎</code> باستخدام التابع <code>Task.Run</code>
</h3>

<p>
	إذا كان الـ <code>Delegate</code> المُمرَّر من النوع <code>Func&lt;T&gt;‎</code>، تُنشَئ مُهمِة (task) من النوع <code>Task&lt;T&gt;‎</code>، بحيث تكون القيمة العائدة من المُهِمّة من النوع T. كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_26" style="">
<span class="typ">Task</span><span class="str">&lt;int&gt;</span><span class="pln"> t </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> sum </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">for</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">500</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
            sum </span><span class="pun">+=</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> sum</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">t</span><span class="pun">.</span><span class="typ">Result</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 124750</span></pre>

<p>
	كما رأينا بالمثال السابق، تُتيِح الخاصية <code>Result</code> بالنوع <code>Task</code> الوُلوج للقيمة العائدة من المُهِمّة.
</p>

<p>
	إذا كانت المُهِمّة تُنفَّذ بشكل غيْر مُتزامِن (asynchronous)، فإن اِستخدَام <code>await</code> لانتظار انتهائها من العَمَل يُعيد القيمة الفعلّية والتي تكون من النوع T، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_28" style="">
<span class="kwd">public</span><span class="pln"> async </span><span class="typ">Task</span><span class="pln"> </span><span class="typ">DoSomeWork</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">WebClient</span><span class="pln"> client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WebClient</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// ‫نظرًا لاستخدام await تسند نتيجة المهمة إلى المتغير </span><span class="pln">
    string response </span><span class="pun">=</span><span class="pln"> await client</span><span class="pun">.</span><span class="typ">DownloadStringTaskAsync</span><span class="pun">(</span><span class="str">"http://somedomain.com"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إلغاء مهمة باستخدام <code>CancellationToken</code>
</h3>

<p>
	يُمكن إلغاء مُهِمّة أثناء تَّنْفيذها من خلال مُفتاح الإلغاء <code>CancellationToken</code>.
</p>

<p>
	تُنشِئ المُهِمّة الأساسية مُفتاح إلغاء (cancellation token) وتُمرِّره لإحدى مُهِمّاتها الفرعية أثناء تَنشِئتها من خلال المُعامِل <code>state</code> بباني كائنات النوع <code>Task</code>. وفي حالة أَرَادت إلغائها، يُمكِنها اِستدعاء التابع <code>cancellationTokenSource.Cancel</code>.
</p>

<p>
	في المقابل، ينبغي للمُهِمّة الفرعية أن تَستدعِي التابع <code>ThrowIfCancellationRequested</code> دَوريًّا لضَمان الاستجابة لطلب الإلغاء. كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_30" style="">
<span class="pln">var cancellationTokenSource </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CancellationTokenSource</span><span class="pun">();</span><span class="pln">
var cancellationToken </span><span class="pun">=</span><span class="pln"> cancellationTokenSource</span><span class="pun">.</span><span class="typ">Token</span><span class="pun">;</span><span class="pln">

var task </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">state</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
        var myCancellationToken </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CancellationToken</span><span class="pun">)</span><span class="pln">state</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"{0} "</span><span class="pun">,</span><span class="pln"> i</span><span class="pun">++);</span><span class="pln">
            </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">);</span><span class="pln">
            myCancellationToken</span><span class="pun">.</span><span class="typ">ThrowIfCancellationRequested</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">
    cancellationToken</span><span class="pun">:</span><span class="pln"> cancellationToken</span><span class="pun">,</span><span class="pln">
    state</span><span class="pun">:</span><span class="pln"> cancellationToken</span><span class="pun">);</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Counting to infinity. Press any key to cancel!"</span><span class="pun">);</span><span class="pln">

task</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
cancellationTokenSource</span><span class="pun">.</span><span class="typ">Cancel</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    task</span><span class="pun">.</span><span class="typ">Wait</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">AggregateException</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    ex</span><span class="pun">.</span><span class="typ">Handle</span><span class="pun">(</span><span class="pln">inner </span><span class="pun">=&gt;</span><span class="pln"> inner is </span><span class="typ">OperationCanceledException</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">$</span><span class="str">"{Environment.NewLine}You have cancelled! Task status is: {task.Status}"</span><span class="pun">);</span><span class="pln">
</span><span class="com">//Canceled</span></pre>

<p>
	تستطيع المُهِمّة الفرعية أيضًا فحص وجود طلب الإلغاء باستخدام التابع <code>IsCancellationRequested</code>، والذي يُعيد قيمة منطقية. يُمكِنها بعد ذلك التبلّيغ عن اعتراض من النوع <code>OperationCanceledException</code>، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_32" style="">
<span class="com">//New task delegate</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
var myCancellationToken </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">CancellationToken</span><span class="pun">)</span><span class="pln">state</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">while</span><span class="pun">(!</span><span class="pln">myCancellationToken</span><span class="pun">.</span><span class="typ">IsCancellationRequested</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"{0} "</span><span class="pun">,</span><span class="pln"> i</span><span class="pun">++);</span><span class="pln">
    </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">$</span><span class="str">"{Environment.NewLine}Ouch, I have been cancelled!!"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">OperationCanceledException</span><span class="pun">(</span><span class="pln">myCancellationToken</span><span class="pun">);</span></pre>

<p>
	لاحظ أنه بالإضافة إلى تمرير مفتاح الإلغاء (cancellation token) للمُعامِل <code>state</code> بباني كائنات النوع <code>Task</code>، فقد مُرِّر مفتاح الإلغاء أيضًا للمُعامِل <code>cancellationToken</code>. يُعدّ ذلك ضروريًا لضَمان انتقال المُهِمّة إلى الحالة <code>Canceled</code> بدلًا من <code>Faulted</code> عند اِستدعاء التابع <code>ThrowIfCancellationRequested</code>. مُرِّر أيضًا مفتاح الإلغاء لمُعامِل باني كائنات النوع <code>OperationCanceledException</code> تمريرًا صريحًا لنفس السبب.
</p>

<h3>
	ضمان منطقية السياق التنفيذي باستخدام النوع <code>AsyncLocal</code>
</h3>

<p>
	يُمكن للمُهِمّة الأساسية (parent task) تمرير بعض البيانات إلى مَهامّها الفرعية (children tasks) باستخدام النوع <code>AsyncLocal</code> الذي يَسمَح بتَوفُّر نُسخة محلية (local) من تلك البيانات لكل مُهِمّة فرعية بشكل لا يُؤثر على البيانات الأصلية ضِمْن المُهِمّة الأساسية (parent task) مما يَضمَن منطقية السياق التَّنْفيذي.
</p>

<p>
	في المثال التالي:
</p>

<p>
	(1): لا يُؤثِر تَغيير قيمة المُتغيّر على بقية المَهامّ الفرعية؛ نظرًا لكَوْنه محلي (local).
</p>

<p>
	(2): تَدَفَّقت القيمة من التابع <code>main</code> إلى المُهِمّة <code>task1</code> ومِنْ ثَمَّ إلى هذه المُهِمّة الفرعية دون أن تَتأثَر بأي تَغيّير قد يقع ضِمْن مُهمات اخرى.
</p>

<p>
	(3): بالمثل، تَدَفَّقت القيمة من التابع <code>main</code> إلى المُهِمّة <code>task1</code> ومِنْ ثَمَّ إلى هذه المُهِمّة الفرعية، لكن في هذه الحالة حَدَث تعديل ضمن المُهِمّة <code>task1</code> والتي تُعدّ ضِمْن سياقها التَّنْفيذي ولذلك تَأثَرت بالتَغيّير.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_34" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">AsyncLocal</span><span class="str">&lt;string&gt;</span><span class="pln"> user </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">AsyncLocal</span><span class="str">&lt;string&gt;</span><span class="pun">();</span><span class="pln">
    user</span><span class="pun">.</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"initial user"</span><span class="pun">;</span><span class="pln">

    </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> user</span><span class="pun">.</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"user from another task"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (1)</span><span class="pln">

    var task1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
        </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">user</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "initial user"</span><span class="pln">

            </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
                </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="com">// "initial user"</span><span class="pln">
                    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">user</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (2)</span><span class="pln">
                </span><span class="pun">}).</span><span class="typ">Wait</span><span class="pun">();</span><span class="pln">

            user</span><span class="pun">.</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"user from task1"</span><span class="pun">;</span><span class="pln">

            </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
                </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="com">// "user from task1"</span><span class="pln">
                    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">user</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (3)</span><span class="pln">
                </span><span class="pun">}).</span><span class="typ">Wait</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">

    task1</span><span class="pun">.</span><span class="typ">Wait</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// "initial user" </span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">user</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملحوظة: المُمارسة المُثلى تكون بقَصر اَستخدَام النوع <code>AsyncLocal</code> على المُتغيّرات من نوع القيمة (value types) أو من النوع غيْر المُتغير (immutable)؛ لأن الخاصية <code>AsynLocal.Value</code> تَحمِل نُسخة من المُتغيّر، بالتالي إذا كان المُتغيّر من النوع المَرجِعي (reference type)، فإنها ستَحمِل مَرجِعًا إلى المُتغيّر الأصلي. يعني ذلك أن أي تَغْيير على قيمة <code>AsynLocal.Value</code> ضِمْن مُهِمّة فرعية معينة -في حالة النوع المَرجِعي- سينعكِس مباشرة على المُتغيّر الأصلى وتباعًا على قيمته ضِمْن المَهامّ الفرعية الأُخرى.
</p>

<h2>
	التعامل مع تجميعة مهام
</h2>

<p>
	يُوفِّر كلا من النوعين <code>Task</code> و <code>Task&lt;T&gt;‎</code> العديد من التوابع للتَعامُل مع تَجمِيعَة مَهامّ.
</p>

<p>
	ينتظر التابعين <code>WaitAll</code> و <code>WhenAll</code> انتهاء تَّنْفيذ جميع المَهامّ ضمن التَجمِيعَة. في المُقابل، ينتظر التابعين <code>WhenAny</code> و <code>WaitAny</code> انتهاء تَّنْفيذ مُهِمّة واحدة فقط.
</p>

<p>
	يَعمَل التابعين <code>WaitAll</code> و <code>WaitAny</code> بصورة مُتزامِنة (synchronous) مما يَتسبب بحُدوث تَعطِّيل (blocking). يُعدّ كلًا من التابعين <code>WhenAll</code> و <code>WhenAny</code> النسخة اللا مُتزامِنة وغيْر المُعَطِّلة (non-blocking/asynchronous) منهما على الترتيب ويُعيدان قيمة من النوع <code>Task</code> يُمكنك انتظار انتهائها من العَمَل باستخدَام <code>await</code>.
</p>

<h3>
	استخدام التابع <code>Task.WaitAll</code>
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_36" style="">
<span class="pln">var tasks </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">).</span><span class="typ">Select</span><span class="pun">(</span><span class="pln">
    n </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Task</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">
        </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"I'm task "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> n</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> n</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">)).</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">

foreach</span><span class="pun">(</span><span class="pln">var task in tasks</span><span class="pun">)</span><span class="pln"> 
    task</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">

</span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WaitAll</span><span class="pun">(</span><span class="pln">tasks</span><span class="pun">);</span><span class="pln">

foreach</span><span class="pun">(</span><span class="pln">var task in tasks</span><span class="pun">)</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">task</span><span class="pun">.</span><span class="typ">Result</span><span class="pun">);</span></pre>

<h3>
	استخدام التابع <code>WaitAny</code>
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_38" style="">
<span class="pln">var allTasks </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">).</span><span class="typ">Select</span><span class="pun">(</span><span class="pln">
    n </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Task</span><span class="str">&lt;int&gt;</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> n</span><span class="pun">)</span><span class="pln">
</span><span class="pun">).</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">

var pendingTasks </span><span class="pun">=</span><span class="pln"> allTasks</span><span class="pun">.</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">

foreach</span><span class="pun">(</span><span class="pln">var task in allTasks</span><span class="pun">)</span><span class="pln"> 
    task</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">while</span><span class="pun">(</span><span class="pln">pendingTasks</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var finishedTask </span><span class="pun">=</span><span class="pln"> pendingTasks</span><span class="pun">[</span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WaitAny</span><span class="pun">(</span><span class="pln">pendingTasks</span><span class="pun">)];</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task {0} finished"</span><span class="pun">,</span><span class="pln"> finishedTask</span><span class="pun">.</span><span class="typ">Result</span><span class="pun">);</span><span class="pln">
    pendingTasks </span><span class="pun">=</span><span class="pln"> pendingTasks</span><span class="pun">.</span><span class="typ">Except</span><span class="pun">(</span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln">finishedTask</span><span class="pun">}).</span><span class="typ">ToArray</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WaitAll</span><span class="pun">(</span><span class="pln">allTasks</span><span class="pun">);</span></pre>

<p>
	ملحوظة: يُعدّ استدعاء <code>WaitAll</code> ضروريًا نظرًا لأن <code>WaitAny</code> لا تُبلِّغ عن الاعتراضات.
</p>

<h3>
	استخدام التابع <code>WhenAll</code>
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_42" style="">
<span class="pln">var random </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">();</span><span class="pln">

</span><span class="typ">IEnumerable</span><span class="pun">&lt;</span><span class="typ">Task</span><span class="str">&lt;int&gt;</span><span class="pun">&gt;</span><span class="pln"> tasks </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">).</span><span class="typ">Select</span><span class="pun">(</span><span class="pln">
    n </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
        </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"I'm task "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> n</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> n</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}));</span><span class="pln">

</span><span class="typ">Task</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;</span><span class="pln"> task </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WhenAll</span><span class="pun">(</span><span class="pln">tasks</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pun">[]</span><span class="pln"> results </span><span class="pun">=</span><span class="pln"> await task</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">string</span><span class="pun">.</span><span class="typ">Join</span><span class="pun">(</span><span class="str">","</span><span class="pun">,</span><span class="pln"> results</span><span class="pun">.</span><span class="typ">Select</span><span class="pun">(</span><span class="pln">n </span><span class="pun">=&gt;</span><span class="pln"> n</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">())));</span><span class="pln">
</span><span class="com">// Output: 1,2,3,4,5</span></pre>

<h3>
	استخدام التابع <code>WhenAny</code>
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_40" style="">
<span class="pln">var random </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">();</span><span class="pln">

</span><span class="typ">IEnumerable</span><span class="pun">&lt;</span><span class="typ">Task</span><span class="str">&lt;int&gt;</span><span class="pun">&gt;</span><span class="pln"> tasks </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Enumerable</span><span class="pun">.</span><span class="typ">Range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">).</span><span class="typ">Select</span><span class="pun">(</span><span class="pln">
    n </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">async</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"I'm task "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> n</span><span class="pun">);</span><span class="pln">
        await </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Delay</span><span class="pun">(</span><span class="pln">random</span><span class="pun">.</span><span class="typ">Next</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="lit">1000</span><span class="pun">));</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> n</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}));</span><span class="pln">

</span><span class="typ">Task</span><span class="pun">&lt;</span><span class="typ">Task</span><span class="str">&lt;int&gt;</span><span class="pun">&gt;</span><span class="pln"> whenAnyTask </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WhenAny</span><span class="pun">(</span><span class="pln">tasks</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Task</span><span class="str">&lt;int&gt;</span><span class="pln"> completedTask </span><span class="pun">=</span><span class="pln"> await whenAnyTask</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"The winner is: task "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> await completedTask</span><span class="pun">);</span><span class="pln">

await </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WhenAll</span><span class="pun">(</span><span class="pln">tasks</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"All tasks finished!"</span><span class="pun">);</span></pre>

<h2>
	معالجة الاعتراضات (Exception Handling)
</h2>

<h3>
	استخدام التابع <code>WaitAll</code>
</h3>

<p>
	يُبلِّغ التابع <code>WaitAll</code> عن اعتراض من النوع <code>AggregateException</code> إذا بَلَّغت مُهِمّة واحدة أو أكثر عن اعتراض. وبالتالي، تستطيع تَضْمِين العبارة البرمجية <code>Task.WaitAll</code> داخل كتلة <code>try..catch</code>، لتتمكن من مُعالجة الاعتراضات، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_44" style="">
<span class="pln">var task1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 1 code starting..."</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">"Oh no, exception from task 1!!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

var task2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 2 code starting..."</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">"Oh no, exception from task 2!!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Starting tasks..."</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WaitAll</span><span class="pun">(</span><span class="pln">task1</span><span class="pun">,</span><span class="pln"> task2</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">AggregateException</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task(s) failed!"</span><span class="pun">);</span><span class="pln">

    foreach</span><span class="pun">(</span><span class="pln">var inner in ex</span><span class="pun">.</span><span class="typ">InnerExceptions</span><span class="pun">)</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">inner</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 1 status is: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> task1</span><span class="pun">.</span><span class="typ">Status</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Faulted</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 2 status is: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> task2</span><span class="pun">.</span><span class="typ">Status</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Faulted</span></pre>

<h3>
	بدون استخدام Wait
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_46" style="">
<span class="pln">var task1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 1 code starting..."</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">"Oh no, exception from task 1!!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

var task2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 2 code starting..."</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">"Oh no, exception from task 2!!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

var tasks </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln">task1</span><span class="pun">,</span><span class="pln"> task2</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Starting tasks..."</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">while</span><span class="pun">(</span><span class="pln">tasks</span><span class="pun">.</span><span class="typ">All</span><span class="pun">(</span><span class="pln">task </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">!</span><span class="pln">task</span><span class="pun">.</span><span class="typ">IsCompleted</span><span class="pun">));</span><span class="pln">

foreach</span><span class="pun">(</span><span class="pln">var task in tasks</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">task</span><span class="pun">.</span><span class="typ">IsFaulted</span><span class="pun">)</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task failed: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln">
                          task</span><span class="pun">.</span><span class="typ">Exception</span><span class="pun">.</span><span class="typ">InnerExceptions</span><span class="pun">.</span><span class="typ">First</span><span class="pun">().</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 1 status is: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> task1</span><span class="pun">.</span><span class="typ">Status</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Faulted</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Task 2 status is: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> task2</span><span class="pun">.</span><span class="typ">Status</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Faulted</span></pre>

<h2>
	تدفق البيانات (Dataflow)
</h2>

<p>
	تُسهِّل مكتبة تَوازِي المَهامّ لتدفق البيانات (TPL Dataflow Library) من البرمجة وفق نموذج تَدَفُّق البيانات (dataflow programming model).
</p>

<p>
	تُوفِّر المكتبة العديد من أنواع كتل تَدَفُّق البيانات (dataflow blocks) والتي يُعدّ كُلا منها هيكل بياني يُستخدَم إمّا كمصدر للبيانات (source) أو كمقصِد (target) أو كليهما (propagator). يُمكن أيضًا تقسيم أنواع كتل التَدَفُّق إلى كتل تَخزين مُؤقت (buffering) تَحمِل البيانات للمستهلكين، وكتل تَّنْفيذية (execution) تُنفِّذ مُفوَّض يُمرَّر إليها، وكتل تجميعية (grouping).
</p>

<p>
	بالإضافة إلى ذلك، تُوفِّر المكتبة العديد من التوابع لإرسال الرسائل واستقبالها من وإلى الكتل المختلفة، البعض منها مُتزامِن (synchronous) والبعض الآخر ليس كذلك.
</p>

<h3>
	استخدام النوع <code>BufferBlock</code> لتنشئة متزامنة لنمط المُنتِج والمُستهلِك (producer-consumer pattern)
</h3>

<p>
	تُصنَف الكتل من النوع <code>BufferBlock</code> ضِمْن كتل التخزين المؤقت (buffering)، وتَعمَل كمصدر ومَقصِد للبيانات (propagator).
</p>

<p>
	يُستخدَم التابعين <code>Post</code> و <code>Receive</code> لكتابة الرسائل (messages) إلى كتل التَدَفُّق واستقبالها منها على الترتيب بشكل مُتزامِن (synchronous).
</p>

<p>
	تُعرِّف الشيفرة التالية صنف المُنتِج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_48" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Producer</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Random</span><span class="pln"> random </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">((</span><span class="typ">int</span><span class="pun">)</span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">UtcNow</span><span class="pun">.</span><span class="typ">Ticks</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// انتج القيمة المُرسلة إلى كتلة التدفق</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> </span><span class="typ">Produce</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var value </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="typ">NextDouble</span><span class="pun">();</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">$</span><span class="str">"Producing value: {value}"</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُعرِّف الشيفرة التالية صنف المُستهلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_50" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Consumer</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">//consume the value that will be received from buffer block</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Consume</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">$</span><span class="str">"Consuming value: {value}"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ كيف ضُمْنت كلًا من شيفرة المُنتِج (producer) والمُستهلِك (consumer) داخل مُهِمّتين مُنفصلتين بحيث يُصبِح من الممكن تَّنْفيذهما بصورة مُتواقِتة (concurrently)، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_52" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">BufferBlock</span><span class="str">&lt;double&gt;</span><span class="pln"> buffer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">BufferBlock</span><span class="str">&lt;double&gt;</span><span class="pun">();</span><span class="pln">

    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pln"> </span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// انشئ مهمة ترسل قيمة قيمة من المُنتج إلى كتلة التدفق كل ثانية</span><span class="pln">
        var producerTask </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
            async </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                var producer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Producer</span><span class="pun">();</span><span class="pln">
                </span><span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    buffer</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="pln">producer</span><span class="pun">.</span><span class="typ">Produce</span><span class="pun">());</span><span class="pln">
                    await </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Delay</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">);</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">});</span><span class="pln">

        </span><span class="com">// انشئ مهمة تستقبل القيم من كتلة التدفق</span><span class="pln">
        var consumerTask </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
            </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                var consumer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Consumer</span><span class="pun">();</span><span class="pln">
                </span><span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">

                </span><span class="pun">{</span><span class="pln">
                    consumer</span><span class="pun">.</span><span class="typ">Consume</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">.</span><span class="typ">Receive</span><span class="pun">());</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">});</span><span class="pln">

        </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WaitAll</span><span class="pun">(</span><span class="kwd">new</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> producerTask</span><span class="pun">,</span><span class="pln"> consumerTask </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	استخدام النوع <code>BufferBlock</code> لتنشئة لا مُتزامِنة لنمط المُنتِج والمُستهلِك
</h3>

<p>
	يُستخدَم التابعين <code>SendAsync</code> و <code>ReceiveAsync</code> لكتابة الرسائل (messages) إلى كتل التَدَفُّق واستقبالها منها على الترتيب بشكل لا مُتزامِن (asynchronous).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_54" style="">
<span class="pln">var bufferBlock </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">BufferBlock</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">
    </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DataflowBlockOptions</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">BoundedCapacity</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1000</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

var cancellationToken </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CancellationTokenSource</span><span class="pun">(</span><span class="typ">TimeSpan</span><span class="pun">.</span><span class="typ">FromSeconds</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)).</span><span class="typ">Token</span><span class="pun">;</span><span class="pln">

var producerTask </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    async </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var random </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">cancellationToken</span><span class="pun">.</span><span class="typ">IsCancellationRequested</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            var value </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="typ">Next</span><span class="pun">();</span><span class="pln">
            await bufferBlock</span><span class="pun">.</span><span class="typ">SendAsync</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> cancellationToken</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

var consumerTask </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
    async </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">await bufferBlock</span><span class="pun">.</span><span class="typ">OutputAvailableAsync</span><span class="pun">())</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            var value </span><span class="pun">=</span><span class="pln"> bufferBlock</span><span class="pun">.</span><span class="typ">Receive</span><span class="pun">();</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">value</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

await </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">WhenAll</span><span class="pun">(</span><span class="pln">producerTask</span><span class="pun">,</span><span class="pln"> consumerTask</span><span class="pun">);</span></pre>

<h3>
	استخدام النوع <code>BlockingCollection</code> لتنشئة حلقة لنمط المنتج والمستهلك
</h3>

<p>
	لا يَقَع النوع <code>BlockingCollection</code> ضِمْن مكتبة تَوازِي المَهامّ لتَدَفُّق البيانات (TPL Dataflow Library)، فهو مجرد تجميعة آمنة خيطيًا (thread-safe)، ويُوفِّر تَّنْفيذًا (implementation) لنمط المُنتِج والمُستهلِك (producer/consumer pattern)، لكنه لا يَتمتَع ببقية الميزات الأُخرى التي تُوفِّرها كتل التَدَفُّق. يُمكنك اِستخدَامه لحل المشاكل البسيطة التي لا تَتطلَّب خط أنابيب (pipeline) معقَّد. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_56" style="">
<span class="pln">var consumerTask </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    foreach</span><span class="pun">(</span><span class="pln">var item in collection</span><span class="pun">.</span><span class="typ">GetConsumingEnumerable</span><span class="pun">())</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Consumed: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> item</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="pln">random</span><span class="pun">.</span><span class="typ">Next</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="lit">1000</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Consumer completed!"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_58" style="">
<span class="pln">var collection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">BlockingCollection</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">
var random </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">();</span><span class="pln">

var producerTask </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> item</span><span class="pun">=</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> item</span><span class="pun">&lt;=</span><span class="lit">10</span><span class="pun">;</span><span class="pln"> item</span><span class="pun">++)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        collection</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">item</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Produced: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> item</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="pln">random</span><span class="pun">.</span><span class="typ">Next</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="lit">1000</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    collection</span><span class="pun">.</span><span class="typ">CompleteAdding</span><span class="pun">();</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Producer completed!"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ضُمنت كلًا من شيفرة المُنتِج (producer) والمُستهِلك (consumer) داخل مُهِمّتين منفصلتين بحيث يُصبِح من المُمكن تَّنْفيذهما بصورة مُتواقِتة (concurrently).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_60" style="">
<span class="typ">Task</span><span class="pun">.</span><span class="typ">WaitAll</span><span class="pun">(</span><span class="pln">producerTask</span><span class="pun">,</span><span class="pln"> consumerTask</span><span class="pun">);</span><span class="pln">

</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Everything completed!"</span><span class="pun">);</span></pre>

<p>
	من الجدير بالذكر أنه في حالة عدم استدعاء التابع <code>CompleteAdding</code>، تستطيع مُتابعة إضافة عناصر للتَجمِيعَة حتى لو أصبح المُستهِلك قيْد التَّنْفيذ. اِستدعِي التابع <code>collection.CompleteAdding()‎</code> فقط عندما تكون متأكدًا أنك لم تَعدْ في حاجة لإضافة المزيد من العناصر.
</p>

<p>
	يُمكن اِستخدَام هذا النوع لتَّنْفيذ نمط عدة مُنتجِين لمُستهِلك وحيد، والذي يعنيّ وجود عدة مصادر للبيانات، تكون مسئولة عن تغذية التَجمِيعَة -من نفس النوع <code>BlockingCollection</code>- بالعناصر، وفي المقابل يَسَحَب مُستهلِك وحيد العناصر ويقوم بمُعالَجتِها بطريقة ما.
</p>

<p>
	لاحظ أنه في حالة عدم استدعاء التابع <code>CompleteAdding</code> وكانت التجميعة فارغة، فان المُعدَّد العائد من <code>collection.GetConsumingEnumerable()‎</code> سيتَسَبَّب بحُدوث تَعطّيل (blocking) إلى أن يُضاف عنصر جديد للتجميعة أو إلى أن يُستدعَى التابع <code>BlockingCollection.CompleteAdding()‎</code>.
</p>

<h3>
	كتابة رسائل إلى كتلة تدفق من النوع <code>ActionBlock</code>
</h3>

<p>
	تُصنَف الكتل من النوع <code>ActionBlock</code> ضِمْن الكتل التَّنْفيذية (execution) حيث تُنفِّذ مُفوَّض <code>Delegate</code> من النوع <code>Action</code> كلما استقبَلت بيانات جديدة، وتَعمَل كمقصِد للبيانات (target) فقط. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_62" style="">
<span class="com">// انشئ كتلة تدفق بحدث لا متزامن</span><span class="pln">
var block </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ActionBlock</span><span class="str">&lt;string&gt;</span><span class="pun">(</span><span class="pln">
    async hostName </span><span class="pun">=&gt;</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">IPAddress</span><span class="pun">[]</span><span class="pln"> ipAddresses </span><span class="pun">=</span><span class="pln"> await </span><span class="typ">Dns</span><span class="pun">.</span><span class="typ">GetHostAddressesAsync</span><span class="pun">(</span><span class="pln">hostName</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">ipAddresses</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

</span><span class="com">// ارسل البيانات إلى كتلة التدفق للمُعالجة</span><span class="pln">
block</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="str">"google.com"</span><span class="pun">);</span><span class="pln"> 
block</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="str">"reddit.com"</span><span class="pun">);</span><span class="pln">
block</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="str">"stackoverflow.com"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// بلغ كتلة التدفق بالتوقف عن استقبال عناصر جديدة</span><span class="pln">
block</span><span class="pun">.</span><span class="typ">Complete</span><span class="pun">();</span><span class="pln"> 

</span><span class="com">// انتظر حتي تنتهي كتلة التدفق من معالجة جميع العناصر</span><span class="pln">
await block</span><span class="pun">.</span><span class="typ">Completion</span><span class="pun">;</span><span class="pln"> </span></pre>

<h3>
	توصيل كتل التدفق لتنشئة خط أنابيب البيانات (data pipelines)
</h3>

<p>
	يُستخدَم التابع <code>LinkTo</code> لتوصيل كتلتي تَدَفُّق (dataflow blocks) بحيث تَعمَل الأولى كمصدر للبيانات (source) والاخرى كمقصِد (target). يعني ذلك أنه بمجرد استقبَال الأولى لرسالة جديدة ومُعالَجتِها، فإنها ستُبلِّغ الكتل المتصلة بها بوجود رسالة جديدة. يُمكنك إنشاء خط أنابيب (pipeline) عن طريق توصيل عدة كتل تَدَفُّق ببعضها. كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_64" style="">
<span class="pln">var httpClient </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HttpClient</span><span class="pun">();</span><span class="pln">

</span><span class="com">// أنشئ كتلة تدفق لاستقبال رابط وإعادة محتوياته كسِلسِلة نصية</span><span class="pln">
var downloaderBlock </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TransformBlock</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;(</span><span class="pln">
    async uri </span><span class="pun">=&gt;</span><span class="pln"> await httpClient</span><span class="pun">.</span><span class="typ">GetStringAsync</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">));</span><span class="pln">

</span><span class="com">// انشئ كتلة تدفق لاستقبال سلسلة نصية وطباعتها على الطرفية</span><span class="pln">
var printerBlock </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ActionBlock</span><span class="str">&lt;string&gt;</span><span class="pun">(</span><span class="pln">
    contents </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">contents</span><span class="pun">));</span><span class="pln">

</span><span class="com">// اجعل كتلة جلب محتويات الروابط مكتملة بمجرد اكتمال كتلة تدفق الطباعة </span><span class="pln">
var dataflowLinkOptions </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DataflowLinkOptions</span><span class="pln"> </span><span class="pun">{</span><span class="typ">PropagateCompletion</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">};</span><span class="pln">

</span><span class="com">// وصل كتلتي التدفق لإنشاء خط أنابيب</span><span class="pln">
downloaderBlock</span><span class="pun">.</span><span class="typ">LinkTo</span><span class="pun">(</span><span class="pln">printerBlock</span><span class="pun">,</span><span class="pln"> dataflowLinkOptions</span><span class="pun">);</span><span class="pln">

</span><span class="com">// أرسل عدة روابط لكتلة التدفق الأولى والتي ستُمرر محتوياتها إلى كتلة التدفق الثانية</span><span class="pln">
downloaderBlock</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="str">"http://youtube.com"</span><span class="pun">);</span><span class="pln">
downloaderBlock</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="str">"http://github.com"</span><span class="pun">);</span><span class="pln">
downloaderBlock</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="str">"http://twitter.com"</span><span class="pun">);</span><span class="pln">
downloaderBlock</span><span class="pun">.</span><span class="typ">Complete</span><span class="pun">();</span><span class="pln"> 
</span><span class="com">// Completion will propagate to printerBlock</span><span class="pln">

await printerBlock</span><span class="pun">.</span><span class="typ">Completion</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Only need to wait for the last block in the pipeline</span></pre>

<h2>
	السياق التزامني (Synchronization Contexts)
</h2>

<p>
	يُعدّ السياق التزامني تمثيلًا تجريديًا (abstract representation) للبيئة التي تُنفَّذ بها الشيفرة.
</p>

<p>
	يُستخدَم عادةً عندما يُريد خيط ما تَّنْفيذ شيفرة ضِمْن خيط آخر. في هذه الحالة، يُلتقَط سياق الخيط المستهدف <code>SynchronizationContext</code>، ويُمرَّر للخيط الفرعي، الذي يستطيع -عند الحاجة- اِستخدَام التابع <code>SynchronizationContext.Post</code> لإرسال مُفوَّض (delegate) إلى سياق الخيط المُلتقَط لضَمان تَّنْفيذ المفوَّض ضِمْن ذلك الخيط.
</p>

<p>
	يكون ذلك بالأخص ضروريًا عند التَعامُل مع مُكوِنات الواجهة (UI component)، والتي لا يمكن تعديل خاصياتها إلا من خلال الخيط المالك الذي انشأها.
</p>

<h3>
	الولوج إلى مُكِونات الواجهة (UI components) من خيوط أخرى
</h3>

<p>
	إذا أردت تغيير خاصية مُكِون واجهة أو نموذج تَحكُم (form control)، مثل صندوق نصي (textbox) أو عنوان (label)، من خيط (thread) آخر غير خيط الواجهة الرسومية المُنشِئ لهذا المُكِون. فلابُدّ من اِستخدَام طرائق مُعينة غيْر التعديل المُباشر، وإلا ستحصل على رسالة الخطأ التالية:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		"العمليات عبر الخيوط غير صالحة: مُحاولة الولوج إلى مُكِون واجهة من خيط آخر غير الخيط الذي أنشأه"
	</p>
</blockquote>

<p>
	فمثلًا، ستؤدي الشيفرة التالية إلى التبلِّيغ عن اعتراض يَحمِل الرسالة السابقة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_66" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> button4_Click</span><span class="pun">(</span><span class="pln">object sender</span><span class="pun">,</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Thread</span><span class="pln"> thread </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">(</span><span class="pln">updatetextbox</span><span class="pun">);</span><span class="pln">
    thread</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> updatetextbox</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    textBox1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"updated"</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<h3>
	استخدام السياق التزامُني <code>SynchronizationContext</code>
</h3>

<p>
	يمكن لخيط بالخلفية (background) تنفيذ شيفرة بخيط الواجهة (UI thread) لتَحْديث إحدى مُكوِنات الواجهة (UI component) من خلال استقبال السياق التزامني لخيط الواجهة من النوع <code>SynchronizationContext</code>، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_68" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">Button_Click</span><span class="pun">(</span><span class="pln">object sender</span><span class="pun">,</span><span class="pln"> </span><span class="typ">EventArgs</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">SynchronizationContext</span><span class="pln"> context </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SynchronizationContext</span><span class="pun">.</span><span class="typ">Current</span><span class="pun">;</span><span class="pln">

    </span><span class="typ">Task</span><span class="pun">.</span><span class="typ">Run</span><span class="pun">(</span><span class="pln">
        </span><span class="pun">()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">for</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="lit">500</span><span class="pun">);</span><span class="pln"> 

                context</span><span class="pun">.</span><span class="typ">Post</span><span class="pun">(</span><span class="typ">ShowProgress</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Work complete on item "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">        </span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_70" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">UpdateCallback</span><span class="pun">(</span><span class="pln">object state</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// يُستدعى هذا التابع من خلال خيط الواجهة فقط ولذلك تُحدث بنجاح</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">MyTextBox</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> state as string</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال بالأعلى، إذا حَاول الخيط الفرعي تَحْديث خاصية مُكوِن الواجهة <code>MyTextBox.Text</code> داخل الحلقة <code>for</code> مباشرة، سيُبلَّغ عن خطأ خيطي (threading). أما إذا أرسل الحَدَث <code>UpdateCallback</code> إلى السياق التزامني <code>SynchronizationContext</code> الخاص بخيط الواجهة (UI thread)، ستتم عملية تَحْديث الصندوق النصي ضِمْن نفس خيط مُكوِنات الواجهة بنجاح.
</p>

<p>
	عمليًا، ينبغي أن تَستخدَم الواجهة <code>System.IProgress</code> لتَحْديث شريط التقدم (progress)؛ حيث يَلتقِط التَّنْفيذ الافتراضي لهذه الواجهة <code>System.Progress</code> سياق المُنشِئ التزامني (synchronisation context) تلقائيًا.
</p>

<h3>
	استخدام التابعين <code>Control.Invoke</code> أو <code>Control.BeginInvoke</code>
</h3>

<p>
	حل آخر هو أن تَستخدِم أحد التابعين <code>Control.Invoke</code> أو <code>Control.BeginInvoke</code> لتَغْيير مُحتوى مُكِون الواجهة -صندوق نصي مثلًا- من خيط آخر غير الخيط المالك لنموذج التحكم (form control). علاوة على ذلك، يُمكنك الاستعانة بالخاصية <code>Control.InvokeRequired</code> لفحص ما إذا كان استدعاء نموذج التحكم ضروريًا أم لا، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_72" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> updatetextbox</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">textBox1</span><span class="pun">.</span><span class="typ">InvokeRequired</span><span class="pun">)</span><span class="pln">
        textBox1</span><span class="pun">.</span><span class="typ">BeginInvoke</span><span class="pun">((</span><span class="typ">Action</span><span class="pun">)(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> textBox1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"updated"</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
        textBox1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"updated"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا كنت ستَحتَاج لتَّنْفيذ ذلك بشكل مُتكرر، فربما من الأفضل تَضْمِين هذه الشيفرة داخل دالة مُوسِعَة (extension) للأنواع القابلة للاستدعاء (invokeable)، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_74" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Extensions</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">BeginInvokeIfRequired</span><span class="pun">(</span><span class="kwd">this</span><span class="pln"> </span><span class="typ">ISynchronizeInvoke</span><span class="pln"> obj</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Action</span><span class="pln"> action</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">obj</span><span class="pun">.</span><span class="typ">InvokeRequired</span><span class="pun">)</span><span class="pln">
            obj</span><span class="pun">.</span><span class="typ">BeginInvoke</span><span class="pun">(</span><span class="pln">action</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> object</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
            action</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وبالتالي يُصبِح تَحْديث صندوق نصي من أي خيط أمرًا يسيرًا، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_76" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> updatetextbox</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    textBox1</span><span class="pun">.</span><span class="typ">BeginInvokeIfRequired</span><span class="pun">(()</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> textBox1</span><span class="pun">.</span><span class="typ">Text</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"updated"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الفرق بين التابعين <code>Control.BeginInvoke</code> و <code>Control.Invoke</code> هو أن الأول يُنفَّذ بشكل غير مُتزامِن (asynchronous) أما الثاني فيُنفَّذ بشكل مُتزامِن (synchronous). يعني ذلك أنه إذا اُستخدِم التابع الأول <code>Control.BeginInvoke</code>، فإن الشيفرة المكتوبة بعد استدعاء هذا التابع ستُنفَّذ بغض النظر عن انتهاء المفوَّض المُمرَّر إلى التابع من عَمَله أم لا. في المقابل، لن تُنفَّذ الشيفرة المكتوبة بعد التابع الثاني <code>Control.Invoke</code> إلا بعد انتهاء المفوَّض من العَمَل. يؤدي ذلك إلى حُدوث تَعطّيل بالخيط الأساسي ويَتسبَّب ببطئ الشيفرة إلى حد كبير خاصةً إذا لجأت إلى استخدام هذا التابع بكثرة. ربما أيضًا قد يَتسبَّب بحُدوث قفل ميت (deadlock) في حالة انتظار خيط الواجهة (GUI thread) انتهاء الخيط الفرعي من عمله أو انتظار تحريره لمَورِد معين.
</p>

<h2>
	استخدام الواجهة IProgress
</h2>

<p>
	لاحظ أن التابع <code>Report</code> مُنفَّذ صراحةً (explicit implementation) ضِمْن الواجهة <code>IProgress</code>، وليس موجودًا ضِمْن النوع المُنفِّذ <code>System.Progress</code>. لذا إمّا أن تَستدعِي التابع من خلال الواجهة أو من خلال النوع لكن بعد أن تُحوّله لنوع الواجهة (casting)، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_83" style="">
<span class="pln">var p1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Progress</span><span class="str">&lt;int&gt;</span><span class="pun">();</span><span class="pln">
p1</span><span class="pun">.</span><span class="typ">Report</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خطأ تصريف</span><span class="pln">

</span><span class="typ">IProgress</span><span class="str">&lt;int&gt;</span><span class="pln"> p2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Progress</span><span class="str">&lt;int&gt;</span><span class="pun">();</span><span class="pln">
p2</span><span class="pun">.</span><span class="typ">Report</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تُصرف بنجاح</span><span class="pln">

var p3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Progress</span><span class="str">&lt;int&gt;</span><span class="pun">();</span><span class="pln">
</span><span class="pun">((</span><span class="typ">IProgress</span><span class="str">&lt;int&gt;</span><span class="pun">)</span><span class="pln">p3</span><span class="pun">).</span><span class="typ">Report</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تُصرف بنجاح</span></pre>

<h3>
	مثال بسيط لتحديث التقدم
</h3>

<p>
	يُمكن لعملية معينة أن تَستخدِم الواجهة <code>IProgress</code> لتَحْديث شريط التقدم لعملية أخرى عن طريق استقبال كائن من الواجهة <code>IProgress</code>، واستدعاء تابعها <code>Report</code> كلما أرادت تَحْديث التقدم، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_79" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">IProgress</span><span class="str">&lt;int&gt;</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Progress</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">
        progress </span><span class="pun">=&gt;</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Running Step: {0}"</span><span class="pun">,</span><span class="pln"> progress</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="typ">LongJob</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3759_81" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">LongJob</span><span class="pun">(</span><span class="typ">IProgress</span><span class="str">&lt;int&gt;</span><span class="pln"> progress</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var max </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> max</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        progress</span><span class="pun">.</span><span class="typ">Report</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخْرج:
</p>

<pre class="ipsCode">
Running Step: 0
Running Step: 3
Running Step: 4
Running Step: 5
Running Step: 6
Running Step: 7
Running Step: 8
Running Step: 9
Running Step: 2
Running Step: 1
</pre>

<p>
	يُنفَّذ التابع <code>IProgress.Report()‎</code> بشكل لا مُتزامِن (asynchronously)، لذلك ربما لا تُطبَع الأرقام بنفس ترتيب الاستدعاء. بالتالي، يُعدّ غير مُلائم عندما يكون التَحْديث وِفق ترتيب الاستدعاء ضروريًا.
</p>

<p>
	ترجمة -وبتصرف- للفصول 38 - 39 - 41 - 42 - 43 - 44 - 31 من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">980</guid><pubDate>Fri, 04 Sep 2020 08:52:45 +0000</pubDate></item><item><title>&#x625;&#x62F;&#x627;&#x631;&#x629; &#x627;&#x644;&#x630;&#x627;&#x643;&#x631;&#x629; &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%B0%D8%A7%D9%83%D8%B1%D8%A9-%D9%81%D9%8A-dot-net-r951/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_07/9.png.5ab724bc683aa4c33b932fbf7a5e607c.png" /></p>

<p>
	تُخزَّن الكائنات المُنشئة باستخدام العَامِل <code>new</code> بقسم الكَوْمَة المُدار في الذاكرة (managed heap). يُوفِّر اطار عمل ‎.Net كَانِس المُهملات (Garbage Collector)، والذي يُدير الذاكرة ويُنْهِي (finalize) الكائنات المهملة دون أيّ تَدَخُّل صريح من المُبرمج.
</p>

<p>
	تَستعرِض بعض الأمثلة التالية طريقة عمل كَانِس المُهملات وسُلوكه بشئ من التفصيل، ويُوضِح بعضها الآخر كيفية إعداد الأنواع بطريقة تَسمَح لكَانِس المُهملات بإدارتها بشكل سليم.
</p>

<h2>
	مفهوم الكائنات الحية والكائنات الميتة
</h2>

<p>
	كقاعدة عامة، يُعدّ الكائن حيًّا (live object) إذا ما زال بالإِمكان إعادة اِستخدَامه، ويُعدّ مَيتًا (dead object) إذا أصبح ذلك غير ممكن. ما يُحدِّد إِمكانية الاستخدَام مِن عدمه هو وجود مُتغيّر أو حَقْل واحد على الأقل يَحمِل مَرجِعًا (reference) إلى مكان الكائن بالذاكرة. في حالة خروج كل مُتغيّرات مَراجِع كائن ما -هذا إن وُجدت أساسًا في مرحلة ما أثناء التَّنفيذ- من النطاق (scope)، يُعدّ الكائن مَيتًا ويُنْهَى (finalize) عند إجراء عملية كَنْس.
</p>

<h3>
	مثال 1
</h3>

<p>
	في الشيفرة التالية، نُعرِّف النوع <code>FinalizableObject</code>، والذي يَحوِي فقط باني النوع (constructor) ومُنْهِيه (finalizer):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_7" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">FinalizableObject</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">FinalizableObject</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Instance initialized"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">FinalizableObject</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Instance finalized"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نُنشئ كائنًا من هذا النوع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_9" style="">
<span class="kwd">new</span><span class="pln"> </span><span class="typ">FinalizableObject</span><span class="pun">();</span><span class="pln"> </span></pre>

<p>
	مما يُنتِج الخْرج التالي بالرغم مِن أننا لم نَستخدِم الكائن بَعْد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_11" style="">
<span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject</span><span class="pln"> initialized</span></pre>

<p>
	لن يُنْهَى الكائن حتى يَنتهي عَمَل البرنامج، والذي يؤدي في الواقع إلى إنهاء جميع الكائنات وتحرير مساحتها من قسم الكَوْمَة بالذاكرة. ومع ذلك يُمكنك استدعاء التابع <code>Collect</code> لإجبار كَانِس المُهملات (Garbage Collector) على إجراء عملية كَنْس خلال لحظة معينة، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_13" style="">
<span class="kwd">new</span><span class="pln"> </span><span class="typ">FinalizableObject</span><span class="pun">();</span><span class="pln"> 
GC</span><span class="pun">.</span><span class="typ">Collect</span><span class="pun">();</span></pre>

<p>
	مما يُنتِج الخْرج التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_15" style="">
<span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject</span><span class="pln"> initialized
</span><span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject</span><span class="pln"> finalized</span></pre>

<p>
	أُنْهيت جميع الكائنات الميتة غير المُستخدَمة (dead objects)، وحُرِّرت مساحتها من قسم الكَوْمَة بالذاكرة بمجرد اِستدعاء كَانِس المُهملات.
</p>

<h3>
	مثال 2
</h3>

<p>
	بِفَرْض أن كلًا من النوعين <code>FinalizableObject1</code> و <code>FinalizableObject2</code> مُشتقَّين من النوع <code>FinalizableObject</code> المُعرَّف مُسبقًا ويَرِثا نفس سُلوك طباعة رسائل التهيئة والإنهاء، نُنشِئ الكائنات التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_17" style="">
<span class="pln">var obj1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FinalizableObject1</span><span class="pun">();</span><span class="pln"> 
var obj2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FinalizableObject2</span><span class="pun">();</span><span class="pln"> 

obj1 </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln"> </span><span class="com">// (1)</span><span class="pln">

GC</span><span class="pun">.</span><span class="typ">Collect</span><span class="pun">();</span><span class="pln"> </span><span class="com">// (2)</span></pre>

<p>
	يكون الخْرج كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_19" style="">
<span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject1</span><span class="pln"> initialized
</span><span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject2</span><span class="pln"> initialized
</span><span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject1</span><span class="pln"> finalized</span></pre>

<p>
	(1) لمّا أُسْنِدت القيمة الفارغة <code>null</code> إلى المُتغيّر <code>obj1</code> (كان يَحمِل مَرجِعا إلى الكائن من النوع <code>FinalizableObject1</code>)، أصبح مِن غير الممكن -بطبيعة الحال- الولوج لهذا الكائن مرة أُخرى وبالتالي عُدّ ميتًا. ولذلك عندما اُستدعِي كَانِس المُهملات في وقت لاحق من تنفيذ الشيفرة (2)، أنهاه وحرَّر مساحته بقسم الكَوْمَة بالذاكرة، ويَظهَر ذلك جَلّيًا من خلال طباعة عبارة المُنْهِي (finalizer). على النقيض، ما يزال هناك مَرجِع للكائن من النوع <code>FinalizableObject2</code> وبالتالي عُدّ حيًّا ولم يُنْهَ.
</p>

<h3>
	مثال 3
</h3>

<p>
	بِفَرْض أن النوع <code>FinalizableObject</code> يَحمِل خاصية عَلّنية (public) من نفس نوعه تُسمَّى <code>OtherObject</code>. ماذا سيحُدث لو كان هناك كائنين ميتين، يَحمِل كلًا منهما مَرجِعًا للآخر؟ كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_21" style="">
<span class="pln">var obj1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FinalizableObject1</span><span class="pun">();</span><span class="pln">
var obj2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FinalizableObject2</span><span class="pun">();</span><span class="pln">

obj1</span><span class="pun">.</span><span class="typ">OtherObject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> obj2</span><span class="pun">;</span><span class="pln">
obj2</span><span class="pun">.</span><span class="typ">OtherObject</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> obj1</span><span class="pun">;</span><span class="pln">

obj1 </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لم يعد هناك مَرجِع للكائن من النوع FinalizableObject1 </span><span class="pln">
obj2 </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لم يعد هناك مَرجِع للكائن من النوع FinalizableObject2</span><span class="pln">

</span><span class="com">// لكن كلا منهما ما يزال يحمل مرجعا للآخر</span><span class="pln">
GC</span><span class="pun">.</span><span class="typ">Collect</span><span class="pun">()</span></pre>

<p>
	يكون الخْرج كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_23" style="">
<span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizedObject1</span><span class="pln"> initialized
</span><span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizedObject2</span><span class="pln"> initialized
</span><span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizedObject1</span><span class="pln"> finalized
</span><span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizedObject2</span><span class="pln"> finalized</span></pre>

<p>
	على الرغم من أن كِلاَ الكائنين يَحمِل مَرجِعا إلى الكائن الآخر، يَقوُم كانس المُهملات بإنهائهما ويُحرِّر مساحتهما من قسم الكَوْمَة بالذاكرة؛ وذلك لعدم وجود أي مَرجِع لهما ضِمْن كائن حيّ.
</p>

<h2>
	المَراجِع الضعيفة (Weak References)
</h2>

<p>
	المَراجِع الضعيفة <code>WeakReference</code> هي -كأيّ مَرجِع- تُشير إلى مكان كائن مُعين بالذاكرة. لا يُعوِّل كَانِس المُهملات على وجود المَراجِع الضعيفة (weak references) عند تقديره لحالة الكائن من حيث كَوْنه حيًا أو ميتًا. وبالتالي، لا يَمنع وجود مَرجِع ضعيف إلى كائن معين كَانِس المُهملات من إنهاء هذا الكائن وتَحرير مساحته بالذاكرة، ومن هنا كان عَدّها ضعيفة (weak).
</p>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_27" style="">
<span class="pln">var weak </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WeakReference</span><span class="pun">&lt;</span><span class="typ">FinalizableObject</span><span class="pun">&gt;(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FinalizableObject</span><span class="pun">());</span><span class="pln">

GC</span><span class="pun">.</span><span class="typ">Collect</span><span class="pun">();</span></pre>

<p>
	يُنتِج الخْرج التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_25" style="">
<span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject</span><span class="pln"> initialized
</span><span class="str">&lt;namespace&gt;</span><span class="pun">.</span><span class="typ">FinalizableObject</span><span class="pln"> finalized</span></pre>

<p>
	حَذَفَ كَانِس المُهملات -عند اِسْتِدْعائه- الكائن من قسم الكَوْمَة بالذاكرة على الرغم من وجود مَرجِعًا إليه من النوع <code>WeakReference</code> داخل النطاق (scope). نَستنتِج من ذلك:
</p>

<p>
	أولًا: مِن غيْر الآمن أن تَفترِض أن المساحة المُخصَّصة بقسم الكَوْمَة لكائن مُشار إليه بمَرجِع ضعيف لا تزال صالحة.
</p>

<p>
	ثانيًا: عندما تحتاج إلى تحصيل (dereference) قيمة مَرجِع ضعيف، اِستخدِم التابع <code>TryGetTarget</code> أولًا والذي يُعيد قيمة منطقية تُحدِّد إذا ما حُرِّرت مساحته بالذاكرة أم لا، ثم اُكتب شيفرة لمُعالجة كِلاَ الحالتين. كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_29" style="">
<span class="pln">var target </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> object</span><span class="pun">();</span><span class="pln"> 
var weak </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WeakReference</span><span class="str">&lt;object&gt;</span><span class="pun">(</span><span class="pln">target</span><span class="pun">);</span><span class="pln"> 

target </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln"> 

</span><span class="com">// فحص ما إذا كان الكائن ما زال مُتاحًا</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">weak</span><span class="pun">.</span><span class="typ">TryGetTarget</span><span class="pun">(</span><span class="pln">out target</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// يُمكنك استخدام الكائن هنا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// لا ينبغي استخدام الكائن هنا</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُوفِّر جميع إصدارات إطار عمل ‎.NET نسخة غير مُعمَّمة من النوع <code>WeakReference</code> والتي تَعمَل بنفس الطريقة. في المقابل، دُعِّمت النسخة المُعمَّمة منذ اصدار 4.5.
</p>

<p>
	انظر المثال التالي للنسخة الغيْر مُعمَّمة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_31" style="">
<span class="pln">var target </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> object</span><span class="pun">();</span><span class="pln"> 
var weak </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">WeakReference</span><span class="pun">(</span><span class="pln">target</span><span class="pun">);</span><span class="pln"> 

target </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln"> 

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">weak</span><span class="pun">.</span><span class="typ">IsAlive</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    target </span><span class="pun">=</span><span class="pln"> weak</span><span class="pun">.</span><span class="typ">Target</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// يُمكنك استخدام الكائن هنا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">// لا ينبغي استخدام الكائن هنا</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التابع <code>Dispose</code> والمنهيات (finalizers)
</h2>

<p>
	إذا أردت التأكد من تحرير الموارد (resources) التي يَستخدِمها كائن مُعين بمجرد أن يَخْرُج من النطاق ويُصبح من غير الممكن اِستخدَامه -خاصة إن كانت الموارد مُستَنزِفة للذاكرة أو غير مُدارة مثل التَعامُل مع الملفات فقد يُبلَّغ عن اعتراض عند محاولة فتح ملف للقراءة ولا يُغلَق مِقبَض الملف (file handle) كما يَنبغي-، صَرِّح عن كَوْن نوع الكائن من الواجهة <code>IDisposable</code> والتي تحتوي على تابع وحيد هو <code>Dispose</code> لا يَستقبِل أي مُعامِلات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_33" style="">
<span class="kwd">public</span><span class="pln"> interface </span><span class="typ">IDisposable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Dispose</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم نفِّذ تابعها <code>Dispose</code> داخل النوع المَذكور بحيث يكون هذا التابع مَسئولًا عن تحرير تلك الموارد.
</p>

<p>
	بخلاف المُنْهِيات (finalizers) التي تُستَدعَى دائمًا عند انتهاء فترة حياة الكائن، يَقع عاتِق اِستِدعاء التابع <code>Dispose</code> على المُبرمِج وهو ما ليس مَضْمُونًا. يُمكن للمُبرمِج اِستِدعاء التابع <code>Dispose</code> صراحةً، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_35" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SomeFunction</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// هيئ كائن يستهلك موارد مستنزفة للذاكرة</span><span class="pln">
    var disposableObject </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ClassThatImplementsIDisposable</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// ‫استدعي التابع Dispose</span><span class="pln">
    disposableObject</span><span class="pun">.</span><span class="typ">Dispose</span><span class="pun">();</span><span class="pln">

    </span><span class="com">// (1)</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	(1): يَخرُج المُتغيّر <code>disposableObject</code> من النطاق (scope). مع ذلك، لا يُمكننا الجزم بموعد إنهاء (finalize) الكائن لنفسه، ولذلك يَضمَن اِستِدعاء التابع <code>Dispose</code> تحرير موارده المُستَنزِفة للذاكرة.
</p>

<p>
	ربما تَستَدعِيها كذلك صراحةً داخل كُتلة <code>finally</code>، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_37" style="">
<span class="typ">StreamReader</span><span class="pln"> sr</span><span class="pun">;</span><span class="pln">
string textFromFile</span><span class="pun">;</span><span class="pln">
string filename </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SomeFile.txt"</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    sr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamReader</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">);</span><span class="pln">
    textFromFile </span><span class="pun">=</span><span class="pln"> sr</span><span class="pun">.</span><span class="typ">ReadToEnd</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
finally
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">sr </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln"> 
        sr</span><span class="pun">.</span><span class="typ">Dispose</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أو من خلال اِستخدَام عبارة <code>using</code> والتي في الواقع يُفضَّل اِستخدَامها، وسيُحوِّلها المُصرِّف آليًا إلى نفس الشيفرة الموجودة بالأعلى، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_39" style="">
<span class="pln">string textFromFile</span><span class="pun">;</span><span class="pln">
string filename </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SomeFile.txt"</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamReader</span><span class="pln"> sr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Streamreader</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    textFromFile </span><span class="pun">=</span><span class="pln"> sr</span><span class="pun">.</span><span class="typ">ReadToEnd</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُعدّ التَعامُل مع الأنواع التي يَكون إطار العمل مسؤولًا عن تَنشِئة كائناتها مثال آخر. في هذه الحالة، عادة ما يُشتقّ النوع الجديد من نوع أساسي (base). مثلًا، عندما تُعْلِن عن نوع مُتَحكِم جديد (controller)، يَرِث من النوع الأساسي <code>System.Web.Mvc.ControllerBase</code>. فإذا كان النوع الأساسي يُنفِّذ الواجهة <code>IDisposable</code>، غالبًا ما يَعني ذلك أن اطار العمل سيَستَدعِي التابع <code>Dispose</code> بطريقة سليمة، ولكن هذا ليس مَضْمُونًا.
</p>

<p>
	لا يُعدّ التابع <code>Dispose</code> بديلًا للمُنْهِي (finalizer)، لكن ينبغي أن تَستخدِم كليهما بحسب الغرض:
</p>

<ul>
<li>
		يُحرِّر المُنْهِي الموارد -على أيّ حال- لتَجَنُّب حُدوث أي تَسرُّب للذاكرة (memory leaks).
	</li>
	<li>
		يُحرِّر التابع <code>Dispose</code> الموارد بمجرد إنتهاء الحاجة إليها؛ لتخفيف الضغط على الذاكرة المُخصَّصة (memory allocation) عامةً.
	</li>
</ul>
<h2>
	استخدام النوع <code>SafeHandle</code> لتغليف الموارد غير المُدارة
</h2>

<p>
	عند كتابة مُغلِّف (wrapper) لموارد غير مُدارة، اِحرص على أن يُشتقّ المُغلِّف من النوع <code>SafeHandle</code> بدلًا من أن تُنفِّذ الواجهة <code>IDisposable</code> أو تُنشِئ مُنْهِي (finalizer) بنفسك، حيث يُنفِّذ هذا النوع بالفعل الواجهة من أجلك، ويُهيِئ المُنْهِيات (finalizers) تهيئة مناسبة، كما يَضمَن تَّنفيذ شيفرة التحرير.
</p>

<p>
	يجب أن يَكون النوع المُشتقّ من الصنف <code>SafeHandle</code> صغيرًا وبسيطًا لتقليل احتمالية تَسريب المِقبَض (handle). يتأكد النوع <code>SafeHandle</code> من تحرير أي موارد غيْر مُدارة حتى في حالة حدوث تَسريب لكائنات المُغلِّف.
</p>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_41" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Runtime</span><span class="pun">.</span><span class="typ">InteropServices</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyHandle</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">SafeHandle</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> override </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">IsInvalid</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> handle </span><span class="pun">==</span><span class="pln"> </span><span class="typ">IntPtr</span><span class="pun">.</span><span class="typ">Zero</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">MyHandle</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> base</span><span class="pun">(</span><span class="typ">IntPtr</span><span class="pun">.</span><span class="typ">Zero</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">MyHandle</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> length</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">SetHandle</span><span class="pun">(</span><span class="typ">Marshal</span><span class="pun">.</span><span class="typ">AllocHGlobal</span><span class="pun">(</span><span class="pln">length</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> override </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">ReleaseHandle</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Marshal</span><span class="pun">.</span><span class="typ">FreeHGlobal</span><span class="pun">(</span><span class="pln">handle</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تنبيه: لا يَتعدَّى المثال بالأعلى كَوْنِه مجرد محاولة لاستعراض طريقة اِشتقاق <code>SafeHandle</code>. وعليه وجب التنبيه أنه من العبث تَخصيص جزء من الذاكرة بهذه الطريقة.
</p>

<h2>
	تحرير الكائنات وإنهائها بشكل سليم
</h2>

<p>
	يَستهدِف كلًا من التابع <code>Dispose</code> والمُنْهِيات (finalizer) ظرفًا مختلفًا. ولذلك، من الضروري للأنواع التي تَستخدِم موارد مُستَنزِفة للذاكرة أن تُنفِّذ كلتا الطريقتين. وبالنتيجة، نحصل على نوع يُمكنه التعامُل المُلائم مع كِلاَ المَوقِفيّن المُحتملين:
</p>

<ul>
<li>
		اِستدعاء المُنْهِي فقط.
	</li>
	<li>
		اِستدعاء التابع Dispose أولًا ثم اِستدعاء المُنْهِي فيما بعد.
	</li>
</ul>
<p>
	أحد الحلول هو كتابة شيفرة التنظيف (cleanup) بطريقة قابلة للتنفيذ أكثر من مرة بدون وجود اختلاف بالنتيجة. تَعتمِد تلك القابلية على طبيعة عملية التنظيف نفسها، على سبيل المثال:
</p>

<ul>
<li>
		<p>
			لا تُحدِث محاولة إغلاق اتصال بقاعدة بيانات (connection) تم إغلاقه مُسبقّا فرقًا.
		</p>
	</li>
	<li>
		<p>
			قد يؤدي تحديث عَداد إلى نتائج خاطئة عند اِستدعاء الشيفرة مرتين بدلًا من مرة واحدة.
		</p>
	</li>
</ul>
<p>
	حل آخر هو التأكد من تَّنفيذ شيفرة التنظيف (cleanup) مرة واحدة فقط بغض النظر عن السياق الخارجي، وهو ما يُمكن عادةً تحقيقه باستخدام مُتغيّر راية (flag) مُخصَّص لهذا الغرض. كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_43" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DisposableFinalizable1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IDisposable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> disposed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">DisposableFinalizable1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Cleanup</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Dispose</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Cleanup</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Cleanup</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(!</span><span class="pln">disposed</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// ضمن الشيفرة الفعلية المسئولة عن تحرير الموارد هنا</span><span class="pln">

            disposed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كذلك يمكن تحقيقه باِستدعاء التابع <code>SuppressFinalize()‎</code> في حالة اِستدعاء التابع <code>Dispose</code>. يُوفِّر كانس المُهملات هذا التابع الذي يَسمَح بتخطي تَّنفيذ المُنْهِي (finalizer)، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9415_45" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DisposableFinalizable2</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">IDisposable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">DisposableFinalizable2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Cleanup</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Dispose</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Cleanup</span><span class="pun">();</span><span class="pln">
        GC</span><span class="pun">.</span><span class="typ">SuppressFinalize</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Cleanup</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ضمن الشيفرة الفعلية المسئولة عن تحرير الموارد هنا</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التخزين المؤقت Caching
</h2>

<p>
	يُوفِّر النوع <code>MemoryCache</code> بإطار عمل <code>‎.NET</code> العديد من التوابع لتخزين البيانات بالذاكرة (memory).
</p>

<h3>
	إضافة عنصر باستخدام التابع <code>Set</code>
</h3>

<p>
	يُستخدَم التابع <code>Set</code> لإضافة مُدخَل إلى الذاكرة المخبئية (cache)، حيث يَستقبَل مُعامل من النوع <code>CacheItem</code> يَحمِل كلًا من مفتاح وقيمة المُدخَل.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6988_7" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">SetToCache</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    string key </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Cache_Key"</span><span class="pun">;</span><span class="pln">
    string value </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Cache_Value"</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// ‫‏احصل على مَرجِع لنُسخة النوع MemoryCache الافتراضية   </span><span class="pln">
    var cacheContainer </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MemoryCache</span><span class="pun">.</span><span class="typ">Default</span><span class="pun">;</span><span class="pln">

    var policy </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CacheItemPolicy</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">AbsoluteExpiration</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTimeOffset</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">.</span><span class="typ">AddMinutes</span><span class="pun">(</span><span class="pln">DEFAULT_CACHE_EXPIRATION_MINUTES</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    var itemToCache </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CacheItem</span><span class="pun">(</span><span class="pln">key</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">);</span><span class="pln"> 
    cacheContainer</span><span class="pun">.</span><span class="typ">Set</span><span class="pun">(</span><span class="pln">itemToCache</span><span class="pun">,</span><span class="pln"> policy</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ استخدام الصنف <code>CacheItemPolicy</code> لضبط توقيت انتهاء صلاحية المُدخَل ومَسحُه من الذاكرة المخبئية.
</p>

<h3>
	جلب أو إضافة عنصر باستخدام التابع <code>AddOrGetExisting</code>
</h3>

<p>
	يَجلِب التابع <code>AddOrGetExisting</code> قيمة المفتاح المُمرَّر إليه من الذاكرة المخبئية (cache) في حالة وجوده. أما إذا لم يُكن موجودًا، فإنه سيَستخدِم المُفوِّض <code>valueFetchFactory</code> المُمرَّر إليه لجَلْب قيمة يُخزِنها بالذاكرة كقيمة للمفتاح المحدَّد ثم يُعيدها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6988_9" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">TValue</span><span class="pln"> </span><span class="typ">GetExistingOrAdd</span><span class="pun">&lt;</span><span class="typ">TValue</span><span class="pun">&gt;(</span><span class="pln">string key</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> minutesForExpiration</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Func</span><span class="pun">&lt;</span><span class="typ">TValue</span><span class="pun">&gt;</span><span class="pln"> valueFetchFactory</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// سيتم تقييم التهيئة المرجأة للنوع فقط في حالة عدم وجود العنصر المطلوب بالذاكرة المخبئية </span><span class="pln">
        var newValue </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Lazy</span><span class="pun">&lt;</span><span class="typ">TValue</span><span class="pun">&gt;(</span><span class="pln">valueFetchFactory</span><span class="pun">);</span><span class="pln">

        </span><span class="typ">CacheItemPolicy</span><span class="pln"> policy </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CacheItemPolicy</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">AbsoluteExpiration</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTimeOffset</span><span class="pun">.</span><span class="typ">Now</span><span class="pun">.</span><span class="typ">AddMinutes</span><span class="pun">(</span><span class="pln">minutesForExpiration</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">

        </span><span class="com">// يعيد العنصر من الذاكرة المخبئية إذا كان موجودًا أو يُضيفه في حالة عدم وجوده</span><span class="pln">
        var cachedItem </span><span class="pun">=</span><span class="pln"> _cacheContainer</span><span class="pun">.</span><span class="typ">AddOrGetExisting</span><span class="pun">(</span><span class="pln">key</span><span class="pun">,</span><span class="pln"> newValue</span><span class="pun">,</span><span class="pln"> policy</span><span class="pun">)</span><span class="pln"> as </span><span class="typ">Lazy</span><span class="pun">&lt;</span><span class="typ">TValue</span><span class="pun">&gt;;</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cachedItem </span><span class="pun">??</span><span class="pln"> newValue</span><span class="pun">).</span><span class="typ">Value</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> excep</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">(</span><span class="typ">TValue</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصول Memory management و Garbage Collection و System.Runtime.Caching.MemoryCache من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">951</guid><pubDate>Thu, 20 Aug 2020 13:03:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x62F;&#x62E;&#x644;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x645;&#x62E;&#x631;&#x62C;&#x627;&#x62A; &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D9%85%D8%AF%D8%AE%D9%84%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%85%D8%AE%D8%B1%D8%AC%D8%A7%D8%AA-%D9%81%D9%8A-dot-net-r950/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_07/8.png.11369454d34e3314914503f3538a8971.png" /></p>

<h2>
	القراءة من والكتابة إلى المجارى القياسية
</h2>

<p>
	يُمثِل النوع <code>Console</code> كلًا من مَجْاري الخْرج والدخْل والخْطأ القياسية ببرامج الطرفية.
</p>

<h3>
	الكتابة إلى مجرى الخرج القياسي Stdout
</h3>

<p>
	يَستقبِل التابع السِلسِلة النصية <code>Hello World</code> ويُرسلها إلى مَجْرى الخْرج القياسي، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_7" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تَتوفَّر بصمات أُخرى من التابع <code>Console.WriteLine</code>. يَستقبِل إحداها مُعامِل من النوع <code>Object</code>، ويُرسله أيضًا إلى مَجْرى الخْرج القياسي، لكن بعد اِستدعاء التابع <code>ToString</code> من خلاله.
</p>

<h3>
	الكتابة إلى مجرى الخطأ القياسي StdErr
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_9" style="">
<span class="pln">var sourceFileName </span><span class="pun">=</span><span class="pln"> </span><span class="str">"NonExistingFile"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">.</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Copy</span><span class="pun">(</span><span class="pln">sourceFileName</span><span class="pun">,</span><span class="pln"> </span><span class="str">"DestinationFile"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    var stdErr </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Error</span><span class="pun">;</span><span class="pln">
    stdErr</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">$</span><span class="str">"Failed to copy '{sourceFileName}': {e.Message}"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	قراءة مجرى الخطأ القياسي الخاص بعملية فرعية (child process)
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_11" style="">
<span class="pln">var errors </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">.</span><span class="typ">StringBuilder</span><span class="pun">();</span><span class="pln">

var process </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Process</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">StartInfo</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ProcessStartInfo</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">RedirectStandardError</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">FileName</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"xcopy.exe"</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">Arguments</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"\"NonExistingFile\" \"DestinationFile\""</span><span class="pun">,</span><span class="pln">
        </span><span class="typ">UseShellExecute</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pln">
    </span><span class="pun">},</span><span class="pln">

</span><span class="pun">};</span><span class="pln">

process</span><span class="pun">.</span><span class="typ">ErrorDataReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">s</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> errors</span><span class="pun">.</span><span class="typ">AppendLine</span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="typ">Data</span><span class="pun">);</span><span class="pln">

process</span><span class="pun">.</span><span class="typ">Start</span><span class="pun">();</span><span class="pln">
process</span><span class="pun">.</span><span class="typ">BeginErrorReadLine</span><span class="pun">();</span><span class="pln">
process</span><span class="pun">.</span><span class="typ">WaitForExit</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">errors</span><span class="pun">.</span><span class="typ">Length</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="com">// something went wrong</span><span class="pln">
    </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">Error</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">$</span><span class="str">"Child process error: \r\n {errors}"</span><span class="pun">);</span></pre>

<h2>
	العمليات على الملفات
</h2>

<p>
	يُوفر النوع <code>File</code> -الموجود بفضاء الاسم <code>System.IO</code>- العديد من التوابع الساكنة (static methods) لإجراء العمليات المختلفة على الملفات، كـقراءة ملف أو حفظ بيانات بملف إِمّا بالكتابة (write) وإِمّا بالإضافة فيه (append) وغيره.
</p>

<h3>
	فحص وجود ملف
</h3>

<p>
	يَستقبِل التابع <code>File.Exists</code> مُعامِلًا من النوع <code>String</code> يحتوي على مسار ملف مُعين (قد يكون المسار نسبيًا relative أو مُطلقًا absolute/fully-qualified)، ثم يُعيد قيمة منطقية (bool) تُحدد ما إذا كان الملف موجودًا أم لا، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_13" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        string filePath </span><span class="pun">=</span><span class="pln"> </span><span class="str">"somePath"</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">if</span><span class="pun">(</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">filePath</span><span class="pun">))</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Exists"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">else</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Does not exist"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كأيّ تابع يُعيد قيمة منطقية، يُمكن استخدامه مع المُعامِل الشرطي الثلاثي <code>:?</code> (ternary)، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_15" style="">
<span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">pathToFile</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"Exists"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"Does not exist"</span><span class="pun">);</span></pre>

<h3>
	قراءة ملف
</h3>

<h4>
	قراءة ملف باستخدام النوع <code>File</code>
</h4>

<p>
	يُوفر النوع <code>File</code> ثلاثة توابع لقراءة البيانات من ملف معين. تَستقبِل التوابع الثلاثة مسار الملف المطلوب قراءته، ولكنها تختلف في طريقة القراءة.
</p>

<ul>
<li>
		التابع <code>File.ReadAllText</code>: يقرأ محتويات الملف بالكامل إلى مُتغيِّر من النوع <code>string</code>.
	</li>
	<li>
		التابع <code>File.ReadAllLines</code>: يقرأ محتويات الملف إلى مصفوفة من السَلاسِل النصية <code>string[]‎</code>، بحيث يُقابل كل عنصر منها سطرًا واحدًا من الملف.
	</li>
	<li>
		التابع <code>File.ReadAllBytes</code>: يُعامِل الملف بِعدّه مجموعة بايتات <code>Bytes</code> ويُعيد مصفوفة بايتات <code>byte[]‎</code>.
	</li>
</ul>
<p>
	لاحظ الأمثلة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_19" style="">
<span class="pln">string fileText </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">ReadAllText</span><span class="pun">(</span><span class="pln">file</span><span class="pun">);</span><span class="pln">
string</span><span class="pun">[]</span><span class="pln"> fileLines </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">ReadAllLines</span><span class="pun">(</span><span class="pln">file</span><span class="pun">);</span><span class="pln">
byte</span><span class="pun">[]</span><span class="pln"> fileBytes </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">ReadAllBytes</span><span class="pun">(</span><span class="pln">file</span><span class="pun">);</span></pre>

<h4>
	قراءة ملف باستخدام النوع <code>StreamReader</code>
</h4>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_21" style="">
<span class="pln">string fullOrRelativePath </span><span class="pun">=</span><span class="pln"> </span><span class="str">"testfile.txt"</span><span class="pun">;</span><span class="pln">
string fileData</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="pln">var reader </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamReader</span><span class="pun">(</span><span class="pln">fullOrRelativePath</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    fileData </span><span class="pun">=</span><span class="pln"> reader</span><span class="pun">.</span><span class="typ">ReadToEnd</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	كتابة ملف
</h3>

<p>
	تختلف كتابة البيانات (writing) بملف عن إضافة بيانات إليه (appending) به. ففي الأولى، تُكتَب البيانات على محتويات الملف الحالية (overwrite)، أما في الثانية، تُضاف البيانات إلى نهاية الملف مما يعني الحفاظ على محتوياته الحالية.
</p>

<p>
	ملحوظة: تُنشِئ جميع التوابع المذكورة بالأسفل الملف بصورة آلية -إذا لم يَكُنْ موجودًا- قبل محاولة إلحاق/كتابة البيانات به.
</p>

<h4>
	كتابة ملف باستخدام النوع <code>File</code>
</h4>

<p>
	يُوفر النوع <code>File</code> ثلاثة توابع لكتابة البيانات (writing) بملف.
</p>

<ul>
<li>
		التابع <code>File.WriteAllText</code>: يَستقبِل سِلسِلة نصية <code>string</code> ويكتبها بالملف.
	</li>
	<li>
		التابع <code>File.WriteAllLines</code>: يَستقبِل مصفوفة من السَلاسِل النصية <code>string[]‎</code> ويَكتِب كل عنصر بها إلى سطر منفصل بالملف.
	</li>
	<li>
		التابع <code>File.WriteAllBytes</code>: يَسمَح بكتابة مصفوفة بايتات <code>byte[]‎</code> بملف.
	</li>
</ul>
<p>
	لاحظ الأمثلة التالية بلغة C#‎:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_23" style="">
<span class="typ">File</span><span class="pun">.</span><span class="typ">WriteAllText</span><span class="pun">(</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> </span><span class="str">"here is some data\nin this file."</span><span class="pun">);</span><span class="pln">
</span><span class="typ">File</span><span class="pun">.</span><span class="typ">WriteAllLines</span><span class="pun">(</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> string</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="str">"here is some data"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"in this file"</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
</span><span class="typ">File</span><span class="pun">.</span><span class="typ">WriteAllBytes</span><span class="pun">(</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">255</span><span class="pln"> </span><span class="pun">});</span></pre>

<p>
	أو بلغة الفيجوال بيسك VB، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_25" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">;</span><span class="pln">
string filename </span><span class="pun">=</span><span class="pln"> </span><span class="str">"c:\path\to\file.txt"</span><span class="pun">;</span><span class="pln">
</span><span class="typ">File</span><span class="pun">.</span><span class="pln">writeAllText</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Text to write\n"</span><span class="pun">);</span></pre>

<h4>
	كتابة ملف باستخدام النوع <code>StreamWriter</code>
</h4>

<p>
	يُمكنك أيضًا الكتابة إلى ملف باستخدام كائن من النوع <code>StreamWriter</code>. عادةً ما يُنشَئ كائن المَجْرَى (stream) ضِمْن كتلة <code>using</code>، مما يَضمَن استدعاء التابع <code>Dispose</code> الذي يُفرّغ المَجْرَى ويُغلقه بمجرد الخروج من الكتلة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_27" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">;</span><span class="pln">
string filename </span><span class="pun">=</span><span class="pln"> </span><span class="str">"c:\path\to\file.txt"</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamWriter</span><span class="pln"> writer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    writer</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Text to Write\n"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بالمثل بلغة الفيجوال بيسك VB، يُمكنك الكتابة إلى الملفات باستخدام كائن من النوع <code>StreamWriter</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_29" style="">
<span class="typ">Dim</span><span class="pln"> filename </span><span class="typ">As</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"c:\path\to\file.txt"</span><span class="pln">
</span><span class="typ">If</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">.</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Then</span><span class="pln">
    </span><span class="typ">Dim</span><span class="pln"> writer </span><span class="typ">As</span><span class="pln"> </span><span class="typ">New</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">.</span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">)</span><span class="pln">
    writer</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"Text to write"</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> vbCrLf</span><span class="pun">)</span><span class="pln"> </span><span class="str">'</span><span class="typ">Add</span><span class="pln"> a newline
    writer</span><span class="pun">.</span><span class="pln">close</span><span class="pun">()</span><span class="pln">
</span><span class="typ">End</span><span class="pln"> </span><span class="typ">If</span></pre>

<h3>
	إضافة بيانات إلى ملف
</h3>

<p>
	يُوفر النوع <code>File</code> ثلاثة توابع لإضافة بيانات إلى ملف (appending).
</p>

<ul>
<li>
		التابع <code>File.AppendAllText</code>: يَستقبِل سِلسِلة نصية <code>string</code> ويُلحِقها بنهاية الملف.
	</li>
	<li>
		التابع <code>File.AppendAllLines</code>: يَستقبِل مصفوفة من السَلاسِل النصية <code>string[]</code> ويُلحِق كل عنصر بها إلى الملف بـسطر منفصل.
	</li>
	<li>
		التابع <code>File.AppendText</code>: يَفتَح مَجْرَى (stream) من النوع <code>StreamWriter</code>. يُلحِق هذا المَجْرَى أي بيانات تُكتَب إليه بنهاية الملف.
	</li>
</ul>
<p>
	لاحظ الأمثلة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_31" style="">
<span class="typ">File</span><span class="pun">.</span><span class="typ">AppendAllText</span><span class="pun">(</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Here is some data that is\nappended to the file."</span><span class="pun">);</span><span class="pln">

</span><span class="typ">File</span><span class="pun">.</span><span class="typ">AppendAllLines</span><span class="pun">(</span><span class="pln">file</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> string</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
    </span><span class="str">"Here is some data that is"</span><span class="pun">,</span><span class="pln"> 
    </span><span class="str">"appended to the file."</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">StreamWriter</span><span class="pln"> stream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">AppendText</span><span class="pun">(</span><span class="pln">file</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    stream</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Here is some data that is"</span><span class="pun">);</span><span class="pln">
    stream</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"appended to the file."</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	حَذْف ملف
</h3>

<p>
	يَحذِف التابع <code>File.Delete</code> الملف في حالة تَوفُّر الصلاحيات المطلوبة، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_33" style="">
<span class="typ">File</span><span class="pun">.</span><span class="typ">Delete</span><span class="pun">(</span><span class="pln">path</span><span class="pun">);</span></pre>

<p>
	ومع ذلك، قد يَحدُث خطأ أثناء تنفيذ التَعلِيمة البرمجية بالأعلى، ربما لأحد الأسباب التالية:
</p>

<ul>
<li>
		<p>
			في حالة عدم تَوفُّر الصلاحيات المطلوبة، ويُبلَّغ عن اعتراض من نوع <code>UnauthorizedAccessException</code>.
		</p>
	</li>
	<li>
		<p>
			إذا كان الملف قَيْد الاستخدام أثناء محاولة الحذف، ويُبلَّغ عن اعتراض من نوع <code>IOException</code>.
		</p>
	</li>
	<li>
		<p>
			في حالة حُدوث خطأ مُنخفِض المستوى (low level) أو كان الملف مُعدّ للقراءة فقط، ويُبلَّغ عن اعتراض من نوع <code>IOException</code>.
		</p>
	</li>
	<li>
		<p>
			إذا لم يَكن الملف مَوجودًا، ويُبلَّغ عن اعتراض من نوع <code>IOException</code>.
		</p>
	</li>
</ul>
<p>
	عادةً ما يتم التحايل على المشكلة الأخيرة باستخدام الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_35" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">path</span><span class="pun">))</span><span class="pln">
    </span><span class="typ">File</span><span class="pun">.</span><span class="typ">Delete</span><span class="pun">(</span><span class="pln">path</span><span class="pun">);</span></pre>

<p>
	مع ذلك فإن هذه الطريقة غير مَضْمُونَة؛ لأنها ليست عملية ذرية (atomic) حيث تَتِم على خُطوتين، فمن الممكن أن يُحذَف الملف -بواسطة عملية أخرى- بَعْد اجتياز عملية الفحص بنجاح وقبل محاولة إجراء الحَذْف الفعلي. لذلك فإن الطريقة الأصح للتعامُل مع عمليات الخْرج والدخْل (I/O) لابد وأن تتضمَّن معالجة للاعتراضات (exception handling)، والتي تعني اتخاذ مسار آخر من الأحداث في حالة فَشَل العملية، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_37" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">path</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">File</span><span class="pun">.</span><span class="typ">Delete</span><span class="pun">(</span><span class="pln">path</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">IOException</span><span class="pln"> exception</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">path</span><span class="pun">))</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln"> 
        </span><span class="com">// قام شخص آخر بحذف الملف</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">UnauthorizedAccessException</span><span class="pln"> exception</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// لا تتوفر الصلاحيات المطلوبة</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنه أحيانًا ما تكون أخطاء الخْرج والدخْل (I/O) مؤقتة (مثلًا قد يكون الملف قَيْد الاستخدام)، وفي حالة استخدام الاتصال الشبكي، قد تُحَلّ المشكلة آليًا دون الحاجة لأيّ إجراء. لذا فمن الشائع إعادة محاولة إجراء عمليات الدخْل والخْرج (I/O) عدة مرات مع الانتظار لمُهلة قصيرة بين كل محاولة وأخرى، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_39" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Delete</span><span class="pun">(</span><span class="pln">string path</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">path</span><span class="pun">))</span><span class="pln">
        </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">=</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">File</span><span class="pun">.</span><span class="typ">Delete</span><span class="pun">(</span><span class="pln">path</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">IOException</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="pln">path</span><span class="pun">))</span><span class="pln">
                </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">==</span><span class="pln"> </span><span class="typ">NumberOfAttempts</span><span class="pun">)</span><span class="pln">
                </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
            </span><span class="typ">Thread</span><span class="pun">.</span><span class="typ">Sleep</span><span class="pun">(</span><span class="typ">DelayBetweenEachAttempt</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="com">// (*)</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">NumberOfAttempts</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">DelayBetweenEachAttempt</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">;</span><span class="pln"> </span><span class="com">// ms</span></pre>

<p>
	إذا كنت تَستخدِّم نظام التشغيل Windows وكان ملف ما مفتوحًا بوَضْع <code>FileShare.Delete</code>، ثم حاولت حَذْف ذلك الملف باستخدام التابع <code>File.Delete</code>، فستُعدّ عملية الحَذْف مقبولة، ولكن في الواقع لن يُحذَف الملف إلا بَعْدَما يُغلق.
</p>

<p>
	(*): // ‫ربما تقوم بنفس الشئ مع الاعتراض <code>UnauthorizedAccessException</code> مع أنه ليس من المحتمل حل مثل هذه المشكلة خلال ثوان.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_41" style="">
<span class="typ">File</span><span class="pun">.</span><span class="typ">WriteAllLines</span><span class="pun">(</span><span class="pln">
    path</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">File</span><span class="pun">.</span><span class="typ">ReadAllLines</span><span class="pun">(</span><span class="pln">path</span><span class="pun">).</span><span class="typ">Where</span><span class="pun">(</span><span class="pln">x </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">!</span><span class="typ">String</span><span class="pun">.</span><span class="typ">IsNullOrWhiteSpace</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)));</span></pre>

<h3>
	نَقْل ملف من مسار إلى آخر
</h3>

<p>
	يَستقبِل التابع <code>File.Move</code> مُعامِلين هما ملف المصدر (source) يُحدد الملف المُراد نَقْله، وملف المَقصِد (destination) يُحدد المسار المطلوب نَقْل ملف المصدر إليه. كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_43" style="">
<span class="typ">File</span><span class="pun">.</span><span class="typ">Move</span><span class="pun">(@</span><span class="str">"C:\TemporaryFile.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">@</span><span class="str">"C:\TemporaryFiles\TemporaryFile.txt"</span><span class="pun">);</span></pre>

<p>
	مع ذلك، قد يَحدُث خطأ أثناء تنفيذ التعليمة البرمجية بالأعلى. على سبيل المثال:
</p>

<ul>
<li>
		ماذا لو كان مُستخدِم البرنامج لا يَملِك قُرْص بعنوان C؟ أو كان يَملِكه، ولكنه غَيّر عنوانه إلى B أو M؟
	</li>
	<li>
		ماذا لو كان ملف المصدر (source) قد نُقل بدون عِلمك؟ أو لم يكن موجودًا من الأساس؟
	</li>
</ul>
<p>
	يُمكن التحايل على تلك المشاكل بالتأكد من وجود ملف المصدر أولًا قبل محاولة نَقْله، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_45" style="">
<span class="pln">string source </span><span class="pun">=</span><span class="pln"> </span><span class="pun">@</span><span class="str">"C:\TemporaryFile.txt"</span><span class="pun">,</span><span class="pln"> destination </span><span class="pun">=</span><span class="pln"> </span><span class="pun">@</span><span class="str">"C:\TemporaryFiles\TemporaryFile.txt"</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">if</span><span class="pun">(</span><span class="typ">File</span><span class="pun">.</span><span class="typ">Exists</span><span class="pun">(</span><span class="str">"C:\TemporaryFile.txt"</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">File</span><span class="pun">.</span><span class="typ">Move</span><span class="pun">(</span><span class="pln">source</span><span class="pun">,</span><span class="pln"> destination</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بهذه الطريقة سـنتأكد من وجود ملف المصدر (source) في تلك اللحظة، مما يعني إمكانية نَقْله إلى مكان آخر. لاحظ أنه أحيانًا، قد لا تكون هذه الطريقة كافية.
</p>

<p>
	أما في حالة لم يَكن الملف موجودًا، قُم بعملية الفحص مُجددًا، وإذا فَشَلت، يُمكنك مُعالجة الاعتراض أو تَبلِّيغ المُستخْدِم بذلك.
</p>

<p>
	ملحوظة: يُعدّ الاعتراض <code>FileNotFoundException</code> واحدًا فقط ضِمْن عِدّة اعتراضات قد تواجهك.
</p>

<p>
	يَعرِض الجدول التالي الاعتراضات المُحتملة:
</p>

<p>
	| نوع الاعتراض | الوصف | | :-------------------------: | :----------------------------------------------------------: | | IOException | إذا كان ملف المقصد موجود بالفعل أو كان ملف المصدر (source) غير موجود | | ArgumentNullException | إذا كانت قيمة ملف المصدر (source) أو ملف المقصد (destination) فارغة | | ArgumentException | إذا كانت قيمة ملف المصدر (source) أو ملف المقصد (destination) فارغة أو تحتوي محارِف غير صالحة | | UnauthorizedAccessException | إذا لم تتَوفَّر الصلاحيات المطلوبة لإجراء العملية | | PathTooLongException | إذا كان ملف المصدر (source) أو ملف المقصد (destination) أو المسارات المحددة تتعدّى الطول المسموح به. | | DirectoryNotFoundException | إذا كان المجلد المُحدد غير موجود | | NotSupportedException | إذا كان مسار ملف المصدر (source) أو ملف المقصد (destination) أو أسماء تلك الملفات بصيغة غير صالحة |
</p>

<h3>
	تَعدِّيد ملفات أقدم من مدة محددة
</h3>

<p>
	يُعرِّف المقطع البرمجي التالي دالة مُساعدة (helpers) تحمل الاسم <code>EnumerateAllFilesOlderThan</code>. تُعدِّد هذه الدالة الملفات الأقدم من عُمر معين بالاعتماد على التابع <code>Directory.EnumerateFiles</code>. تُعدّ هذه الدالة مفيدة لحذْف ملفات التسجيل (log files) القديمة أو البيانات المُخزَّنة مؤقتًا (cached).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_47" style="">
<span class="kwd">static</span><span class="pln"> </span><span class="typ">IEnumerable</span><span class="str">&lt;string&gt;</span><span class="pln"> </span><span class="typ">EnumerateAllFilesOlderThan</span><span class="pun">(</span><span class="pln">
    </span><span class="typ">TimeSpan</span><span class="pln"> maximumAge</span><span class="pun">,</span><span class="pln">
    string path</span><span class="pun">,</span><span class="pln">
    string searchPattern </span><span class="pun">=</span><span class="pln"> </span><span class="str">"*.*"</span><span class="pun">,</span><span class="pln">
    </span><span class="typ">SearchOption</span><span class="pln"> options </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SearchOption</span><span class="pun">.</span><span class="typ">TopDirectoryOnly</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">DateTime</span><span class="pln"> oldestWriteTime </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Now</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> maximumAge</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Directory</span><span class="pun">.</span><span class="typ">EnumerateFiles</span><span class="pun">(</span><span class="pln">path</span><span class="pun">,</span><span class="pln"> searchPattern</span><span class="pun">,</span><span class="pln"> options</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">.</span><span class="typ">Where</span><span class="pun">(</span><span class="pln">x </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Directory</span><span class="pun">.</span><span class="typ">GetLastWriteTime</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> oldestWriteTime</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُمكن استدعائها كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_49" style="">
<span class="pln">var oldFiles </span><span class="pun">=</span><span class="pln"> </span><span class="typ">EnumerateAllFilesOlderThan</span><span class="pun">(</span><span class="typ">TimeSpan</span><span class="pun">.</span><span class="typ">FromDays</span><span class="pun">(</span><span class="lit">7</span><span class="pun">),</span><span class="pln"> </span><span class="pun">@</span><span class="str">"c:\log"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"*.log"</span><span class="pun">);</span></pre>

<p>
	تَستخْدِم الدالة المُساعِدّة بالأعلى التابع <code>Directory.EnumerateFiles()‎</code> بدلًا من التابع <code>Directory.GetFiles()‎</code>. لذا لن تحتاج أن تنتظر جَلْب جميع الملفات قبل البدء بمعالجتها.
</p>

<p>
	تَفحَّص الدالة المُساعِدّة توقيت آخِر كتابة (last write time)، ولكن يمكنك أيضًا الاعتماد على وقت الإنشاء (creation time) أو وقت آخر وصول (last access time) وقد يكون ذلك مُفيدًا لحذْف ملفات التخزين المؤقت غير المُستخدَمة. انتبه فقد يكون وقت الوصول غيْر مُفعّل.
</p>

<h3>
	حذف سطور من ملف نصي
</h3>

<p>
	لا يُعدّ التعديل على الملفات النصية أمرًا يسيرًا؛ لأنه لابُدّ من قراءة محتواها أولًا.
</p>

<p>
	إذا كان حجم الملف صغيرًا، فإن أسهل طريقة هي قراءة الملف بالكامل إلى الذاكرة (memory)، وإجراء التعديلات، ثم إعادة كتابة النص المُعدّل إلى الملف.
</p>

<p>
	في المثال التالي، قُرِأت كل سطور الملف، وحُذْف الفارغ منها، ثم كُتبت بملف بنفس المسار.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_51" style="">
<span class="typ">File</span><span class="pun">.</span><span class="typ">WriteAllLines</span><span class="pun">(</span><span class="pln">path</span><span class="pun">,</span><span class="pln">
                   </span><span class="typ">File</span><span class="pun">.</span><span class="typ">ReadAllLines</span><span class="pun">(</span><span class="pln">path</span><span class="pun">).</span><span class="typ">Where</span><span class="pun">(</span><span class="pln">x </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">!</span><span class="typ">String</span><span class="pun">.</span><span class="typ">IsNullOrWhiteSpace</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)));</span></pre>

<p>
	أما إذا كان الملف كبيرًا لتقرأه بالكامل إلى الذاكرة، فيُفضَّل استخدام التابع <code>File.ReadLines</code> الذي يُعيد معدَّد من السَلاسِل النصية <code>IEnumerable&lt;string&gt;‎</code>. بهذه الطريقة، يُمكنك البدء بتعدِّيد التَجمِيعَة ومُعالجتها بدون استرجاعها بالكامل، بِعَكْس التابع <code>File.ReadAllLines</code> الذي لابُدّ عند استخدامه من الانتظار حتي تُقرأ محتويات الملف بالكامل إلى مصفوفة <code>string[]‎</code>، وبعدها يُمكن البدء بعملية المُعالجة.
</p>

<p>
	لكن انتبه، في هذه الحالة، سيختلف مسار كلًا من مَلفّي الدخْل والخْرج.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_53" style="">
<span class="typ">File</span><span class="pun">.</span><span class="typ">WriteAllLines</span><span class="pun">(</span><span class="pln">outputPath</span><span class="pun">,</span><span class="pln">
                   </span><span class="typ">File</span><span class="pun">.</span><span class="typ">ReadLines</span><span class="pun">(</span><span class="pln">inputPath</span><span class="pun">).</span><span class="typ">Where</span><span class="pun">(</span><span class="pln">x </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">!</span><span class="typ">String</span><span class="pun">.</span><span class="typ">IsNullOrWhiteSpace</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)));</span></pre>

<h3>
	تغيير ترميز ملف نصي
</h3>

<p>
	تُخزَّن النصوص مرمَّزة (enocoded). أحيانًا قد ترغب بتَغْيير الترميز المُستخدَم، وعندها يُمكنك تمرير مُعامِل إضافي من النوع <code>Encoding</code> للتابع <code>WriteAllText</code>؛ لتخصيص الترميز المطلوب، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_55" style="">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ConvertEncoding</span><span class="pun">(</span><span class="pln">string path</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pln"> from</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Encoding</span><span class="pln"> to</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">File</span><span class="pun">.</span><span class="typ">WriteAllText</span><span class="pun">(</span><span class="pln">path</span><span class="pun">,</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">ReadAllText</span><span class="pun">(</span><span class="pln">path</span><span class="pun">,</span><span class="pln"> from</span><span class="pun">),</span><span class="pln"> to</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملحوظة: افترضنا أن الملف صغيرًا كفاية ليُقرأ بالكامل إلى الذاكرة بغرض التبسيط.
</p>

<p>
	قد يحتوي الملف على BOM. يُمكنك الاطلاع على <a href="http://stackoverflow.com/q/11701341/1207195" rel="external nofollow">"لا يأخذ التابع Encoding.UTF8.GetString بالحسبان Preamble/BOM"</a> لفهم أعمق لكيفية التعامل معها.
</p>

<h3>
	التعامل مع الملفات بامتداد Zip
</h3>

<h4>
	عَرْض قائمة محتويات ملف بامتداد Zip
</h4>

<p>
	تقوم الشيفرة التالية بعَرْض قائمة بأسماء الملفات الموجودة بملف أرشيفي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_57" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileStream</span><span class="pln"> fs </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileStream</span><span class="pun">(</span><span class="str">"archive.zip"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FileMode</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ZipArchive</span><span class="pln"> archive </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ZipArchive</span><span class="pun">(</span><span class="pln">fs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ZipArchiveMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> archive</span><span class="pun">.</span><span class="typ">Entries</span><span class="pun">.</span><span class="typ">Count</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">$</span><span class="str">"{i}: {archive.Entries[i]}"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أن أسماء الملفات تكون نسبية (relative) وفقًا للملف الأرشيفي.
</p>

<h4>
	استخراج (Extracting) محتويات ملف بامتداد Zip
</h4>

<p>
	يَستخرِج التابع <code>ExtractToDirectory</code> الملفات الموجودة ضِمْن ملف أرشيفي كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_59" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileStream</span><span class="pln"> fs </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileStream</span><span class="pun">(</span><span class="str">"archive.zip"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FileMode</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ZipArchive</span><span class="pln"> archive </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ZipArchive</span><span class="pun">(</span><span class="pln">fs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ZipArchiveMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    archive</span><span class="pun">.</span><span class="typ">ExtractToDirectory</span><span class="pun">(</span><span class="pln">
        </span><span class="typ">AppDomain</span><span class="pun">.</span><span class="typ">CurrentDomain</span><span class="pun">.</span><span class="typ">BaseDirectory</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيُبلَّغ عن اعتراض من النوع <code>System.IO.IOException</code> إذا كان المجلد المُستخرَج إليه يحتوي على ملف يحمل نفس الاسم.
</p>

<p>
	يُمكنك اِستِخراج ملفات بعينها. فمثلًا، يُستخدَم التابع <code>GetEntry</code> لاختيار ملف معين عن طريق اسمه تمهيدًا لاستخراجه باستخدام التابع <code>ExtractToFile</code>. يُمكنك أيضًا الولوج للخاصية <code>Entries</code> والبحث فيها عن ملف يُحقق شرطًا معينًا، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_61" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileStream</span><span class="pln"> fs </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileStream</span><span class="pun">(</span><span class="str">"archive.zip"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FileMode</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ZipArchive</span><span class="pln"> archive </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ZipArchive</span><span class="pun">(</span><span class="pln">fs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ZipArchiveMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">         
    </span><span class="com">// اختر ملف بالمجلد الرئيسي</span><span class="pln">
    archive</span><span class="pun">.</span><span class="typ">GetEntry</span><span class="pun">(</span><span class="str">"test.txt"</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">.</span><span class="typ">ExtractToFile</span><span class="pun">(</span><span class="str">"test_extracted_getentries.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// أضف مسارًا إذا كنت تريد استهداف ملف بـمجلد فرعي</span><span class="pln">
    archive</span><span class="pun">.</span><span class="typ">GetEntry</span><span class="pun">(</span><span class="str">"sub/subtest.txt"</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">.</span><span class="typ">ExtractToFile</span><span class="pun">(</span><span class="str">"test_sub.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">

    archive</span><span class="pun">.</span><span class="typ">Entries</span><span class="pln">
        </span><span class="pun">.</span><span class="typ">FirstOrDefault</span><span class="pun">(</span><span class="pln">f </span><span class="pun">=&gt;</span><span class="pln"> f</span><span class="pun">.</span><span class="typ">Name</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"test.txt"</span><span class="pun">)?</span><span class="pln">
        </span><span class="pun">.</span><span class="typ">ExtractToFile</span><span class="pun">(</span><span class="str">"test_extracted_linq.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا اخترت اسم ملف غير موجود، سُيبلَّغ عن اعتراض من النوع <code>System.ArgumentNullException</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_63" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileStream</span><span class="pln"> fs </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileStream</span><span class="pun">(</span><span class="str">"archive.zip"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FileMode</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ZipArchive</span><span class="pln"> archive </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ZipArchive</span><span class="pun">(</span><span class="pln">fs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ZipArchiveMode</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">    
    archive</span><span class="pun">.</span><span class="typ">GetEntry</span><span class="pun">(</span><span class="str">"nonexistingfile.txt"</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">.</span><span class="typ">ExtractToFile</span><span class="pun">(</span><span class="str">"fail.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h4>
	تحديث ملف بامتداد Zip
</h4>

<p>
	لتحديث ملف بامتداد zip، يجب فتح الملف باستخدام الوَضْع <code>ZipArchiveMode.Update</code>، حتى تستطيع إضافة ملفات جديدة إليه. يُستخدَم التابع <code>CreateEntryFromFile</code> لإضافة ملف للمجلد الرئيسي أو لمجلد فرعي، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_65" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileStream</span><span class="pln"> fs </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">FileStream</span><span class="pun">(</span><span class="str">"archive.zip"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FileMode</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ZipArchive</span><span class="pln"> archive </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ZipArchive</span><span class="pun">(</span><span class="pln">fs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ZipArchiveMode</span><span class="pun">.</span><span class="typ">Update</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// أضف ملف إلى الأرشيف</span><span class="pln">
    archive</span><span class="pun">.</span><span class="typ">CreateEntryFromFile</span><span class="pun">(</span><span class="str">"test.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"test.txt"</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// أضيف ملف إلى مجلد فرعي بالملف الأرشيفي</span><span class="pln">
    archive</span><span class="pun">.</span><span class="typ">CreateEntryFromFile</span><span class="pun">(</span><span class="str">"test.txt"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"symbols/test.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُمكن أيضًا الكتابة مباشرة بملف داخل الأرشيف باستخدام التابع <code>CreateEntry</code>، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_67" style="">
<span class="pln">var entry </span><span class="pun">=</span><span class="pln"> archive</span><span class="pun">.</span><span class="typ">CreateEntry</span><span class="pun">(</span><span class="str">"createentry.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">using</span><span class="pun">(</span><span class="pln">var writer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StreamWriter</span><span class="pun">(</span><span class="pln">entry</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">()))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    writer</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Test line"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	القراءة من والكتابة إلى المَنافِذ التَسلسُليّة (Serial Ports)
</h2>

<p>
	يُوفِّر اطار عمل <code>‎.NET</code> النوع <code>SerialPort</code> بفضاء الاسم <code>System.IO.Ports</code> للاتصالات التَسلسُليّة (serial communication).
</p>

<h3>
	عرض قائمة بأسماء المَنافِذ المتاحة
</h3>

<p>
	يُعيدّ التابع <code>SerialPort.GetPortNames()‎</code> قائمة بأسماء المَنافِذ المتاحة، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_69" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">.</span><span class="typ">Ports</span><span class="pun">;</span><span class="pln">
string</span><span class="pun">[]</span><span class="pln"> ports </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SerialPort</span><span class="pun">.</span><span class="typ">GetPortNames</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> ports</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">ports</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	تنشئة كائن من النوع <code>SerialPort</code>
</h3>

<p>
	يُمثِل كائن من النوع <code>SerialPort</code> مَنفَذ تَسلسُليّ مُعين، ويُستخدَم لإرسال الرسائل النصية واستقبالها عبْر ذلك المَنفَذ. تُنشِئ الشيفرة التالية كائنات من النوع <code>SerialPort</code> باستخدَام بَوانِي الكائن:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_71" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">.</span><span class="typ">Ports</span><span class="pun">;</span><span class="pln">
</span><span class="typ">SerialPort</span><span class="pln"> port </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SerialPort</span><span class="pun">();</span><span class="pln">
</span><span class="typ">SerialPort</span><span class="pln"> port </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SerialPort</span><span class="pun">(</span><span class="str">"COM 1"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="typ">SerialPort</span><span class="pln"> port </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SerialPort</span><span class="pun">(</span><span class="str">"COM 1"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9600</span><span class="pun">);</span></pre>

<h3>
	قراءة وكتابة البيانات من وإلى المَنافِذ التَسلسُليّة
</h3>

<p>
	يُعدّ اِستخدَام التابعين <code>SerialPort.Read</code> و <code>SerialPort.Write</code> من أسهل الطرائق للقراءة من والكتابة إلى المَنافِذ التَسلسُليّة على الترتيب، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_73" style="">
<span class="typ">int</span><span class="pln"> length </span><span class="pun">=</span><span class="pln"> port</span><span class="pun">.</span><span class="typ">BytesToRead</span><span class="pun">;</span><span class="pln">

byte</span><span class="pun">[]</span><span class="pln"> buffer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="pln">length</span><span class="pun">];</span><span class="pln">
port</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> length</span><span class="pun">);</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_77" style="">
<span class="pln">port</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"here is some text"</span><span class="pun">);</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_75" style="">
<span class="pln">byte</span><span class="pun">[]</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">255</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
port</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> data</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">);</span></pre>

<p>
	يُمكِن قراءة جميع البيانات المُتوفِّرة باستخدام التابع <code>ReadExisting</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_79" style="">
<span class="pln">string curData </span><span class="pun">=</span><span class="pln"> port</span><span class="pun">.</span><span class="typ">ReadExisting</span><span class="pun">();</span></pre>

<p>
	أو قراءة السطر التالي باستخدام التابع <code>ReadLine</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_81" style="">
<span class="pln">string line </span><span class="pun">=</span><span class="pln"> port</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span></pre>

<p>
	مثال آخر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_83" style="">
<span class="pln">var serialPort </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SerialPort</span><span class="pun">(</span><span class="str">"COM1"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9600</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Parity</span><span class="pun">.</span><span class="typ">Even</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="typ">StopBits</span><span class="pun">.</span><span class="typ">One</span><span class="pun">);</span><span class="pln">

serialPort</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">();</span><span class="pln">

serialPort</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Test data"</span><span class="pun">);</span><span class="pln">
string response </span><span class="pun">=</span><span class="pln"> serialPort</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span><span class="pln">
</span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">response</span><span class="pun">);</span><span class="pln">

serialPort</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span></pre>

<p>
	يُمكن أيضًا استخدام التابع <code>SerialPort.BaseStream</code> لتنشئة مَجْرى من النوع <code>System.IO.Stream</code>، واِستخدَامه لكتابة البيانات إلى المَنفَذ.
</p>

<h3>
	خدمة صَدَى نصي مُتزامِنة (synchronous)
</h3>

<p>
	يُستخدَم التابع <code>ReadLine</code> لقراءة سطر من مَنفَذ من النوع <code>SerialPort</code> بشكل مُتزامِن (synchronous) مما يعني التَسبُّب بتعطيل (blocking) في حالة عدم توفُّر سطر للقراءة.
</p>

<p>
	تَستعرِض الشيفرة التالية خِدمة صدى نصي (text echo) بسيطة بحيث تَبقَى الشيفرة في وَضْع اِستماع للمَنْفَذ إلى حين وصول سطر جديد. عندها يُقرأ السطر ويُعاد إرساله عبر نفس المَنْفَذ إلا في حالة كان يَحوِي السِلسِلة النصية quit.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_85" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">.</span><span class="typ">Ports</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">TextEchoService</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            var serialPort </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SerialPort</span><span class="pun">(</span><span class="str">"COM1"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9600</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Parity</span><span class="pun">.</span><span class="typ">Even</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="typ">StopBits</span><span class="pun">.</span><span class="typ">One</span><span class="pun">);</span><span class="pln">
            serialPort</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">();</span><span class="pln">

            string message </span><span class="pun">=</span><span class="pln"> </span><span class="str">""</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">message </span><span class="pun">!=</span><span class="pln"> </span><span class="str">"quit"</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                message </span><span class="pun">=</span><span class="pln"> serialPort</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span><span class="pln">
                serialPort</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="pln">message</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">

            serialPort</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	قراءة غير متزامنة (asynchronous)
</h3>

<p>
	يُوفِّر النوع <code>SerialPort</code> مجموعة من الأحداث (events) مما يَسمَح بكتابة شيفرة غير مُتزامِنة (asynchronous).
</p>

<p>
	مثلا، يُثار الحَدَث <code>DataReceived</code> عند استقبال بيانات عبر المَنفَذ (port). وبالتالي، يُمكن لمُعالِج حَدَث (event handler) التسجيل (subscribe) بالحَدَث المذكور وقراءة البيانات المُستلَمة بطريقة غير مُتزامِنة، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_87" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">SetupAsyncRead</span><span class="pun">(</span><span class="typ">SerialPort</span><span class="pln"> serialPort</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    serialPort</span><span class="pun">.</span><span class="typ">DataReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">sender</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        byte</span><span class="pun">[]</span><span class="pln"> buffer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">4096</span><span class="pun">];</span><span class="pln">
        </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="typ">EventType</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">case</span><span class="pln"> </span><span class="typ">SerialData</span><span class="pun">.</span><span class="typ">Chars</span><span class="pun">:</span><span class="pln">
                var port </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">SerialPort</span><span class="pun">)</span><span class="pln">sender</span><span class="pun">;</span><span class="pln">
                </span><span class="typ">int</span><span class="pln"> bytesToRead </span><span class="pun">=</span><span class="pln"> port</span><span class="pun">.</span><span class="typ">BytesToRead</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">bytesToRead </span><span class="pun">&gt;</span><span class="pln"> buffer</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">)</span><span class="pln">
                    </span><span class="typ">Array</span><span class="pun">.</span><span class="typ">Resize</span><span class="pun">(</span><span class="pln">ref buffer</span><span class="pun">,</span><span class="pln"> bytesToRead</span><span class="pun">);</span><span class="pln">
                </span><span class="typ">int</span><span class="pln"> bytesRead </span><span class="pun">=</span><span class="pln"> port</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> bytesToRead</span><span class="pun">);</span><span class="pln">
                </span><span class="com">// يمكنك معالجة البيانات المقروءة هنا</span><span class="pln">

                </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">case</span><span class="pln"> </span><span class="typ">SerialData</span><span class="pun">.</span><span class="typ">Eof</span><span class="pun">:</span><span class="pln">
                </span><span class="com">// انهي العملية هنا</span><span class="pln">
                </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	مُستقبِل رسائل غير مُتزامِن (asynchronous)
</h3>

<p>
	تَعرِض الشيفرة التالية مُستقبِل رسائل مَبني على المثال السابق:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_2668_89" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Collections</span><span class="pun">.</span><span class="typ">Generic</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="pln">IO</span><span class="pun">.</span><span class="typ">Ports</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Text</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Threading</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">AsyncReceiver</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Program</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> byte STX </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x02</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> byte ETX </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x03</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> byte ACK </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x06</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> byte NAK </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x15</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">ManualResetEvent</span><span class="pln"> terminateService </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ManualResetEvent</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> readonly object eventLock </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> object</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">List</span><span class="str">&lt;byte&gt;</span><span class="pln"> unprocessedBuffer </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">(</span><span class="pln">string</span><span class="pun">[]</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">try</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                var serialPort </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SerialPort</span><span class="pun">(</span><span class="str">"COM11"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9600</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Parity</span><span class="pun">.</span><span class="typ">Even</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="typ">StopBits</span><span class="pun">.</span><span class="typ">One</span><span class="pun">);</span><span class="pln">
                serialPort</span><span class="pun">.</span><span class="typ">DataReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="typ">DataReceivedHandler</span><span class="pun">;</span><span class="pln">
                serialPort</span><span class="pun">.</span><span class="typ">ErrorReceived</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="typ">ErrorReceivedHandler</span><span class="pun">;</span><span class="pln">
                serialPort</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">();</span><span class="pln">
                terminateService</span><span class="pun">.</span><span class="typ">WaitOne</span><span class="pun">();</span><span class="pln">
                serialPort</span><span class="pun">.</span><span class="typ">Close</span><span class="pun">();</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Exception occurred: {0}"</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadKey</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">DataReceivedHandler</span><span class="pun">(</span><span class="pln">object sender</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SerialDataReceivedEventArgs</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            lock </span><span class="pun">(</span><span class="pln">eventLock</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                byte</span><span class="pun">[]</span><span class="pln"> buffer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[</span><span class="lit">4096</span><span class="pun">];</span><span class="pln">
                </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="typ">EventType</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="kwd">case</span><span class="pln"> </span><span class="typ">SerialData</span><span class="pun">.</span><span class="typ">Chars</span><span class="pun">:</span><span class="pln">
                        var port </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">SerialPort</span><span class="pun">)</span><span class="pln">sender</span><span class="pun">;</span><span class="pln">
                        </span><span class="typ">int</span><span class="pln"> bytesToRead </span><span class="pun">=</span><span class="pln"> port</span><span class="pun">.</span><span class="typ">BytesToRead</span><span class="pun">;</span><span class="pln">
                        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">bytesToRead </span><span class="pun">&gt;</span><span class="pln"> buffer</span><span class="pun">.</span><span class="typ">Length</span><span class="pun">)</span><span class="pln">
                            </span><span class="typ">Array</span><span class="pun">.</span><span class="typ">Resize</span><span class="pun">(</span><span class="pln">ref buffer</span><span class="pun">,</span><span class="pln"> bytesToRead</span><span class="pun">);</span><span class="pln">
                        </span><span class="typ">int</span><span class="pln"> bytesRead </span><span class="pun">=</span><span class="pln"> port</span><span class="pun">.</span><span class="typ">Read</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> bytesToRead</span><span class="pun">);</span><span class="pln">
                        </span><span class="typ">ProcessBuffer</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">,</span><span class="pln"> bytesRead</span><span class="pun">);</span><span class="pln">
                        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
                    </span><span class="kwd">case</span><span class="pln"> </span><span class="typ">SerialData</span><span class="pun">.</span><span class="typ">Eof</span><span class="pun">:</span><span class="pln">
                        terminateService</span><span class="pun">.</span><span class="typ">Set</span><span class="pun">();</span><span class="pln">
                        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ErrorReceivedHandler</span><span class="pun">(</span><span class="pln">object sender</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SerialErrorReceivedEventArgs</span><span class="pln"> e</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            lock </span><span class="pun">(</span><span class="pln">eventLock</span><span class="pun">)</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="typ">EventType</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="typ">SerialError</span><span class="pun">.</span><span class="typ">TXFull</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Error: TXFull. Can't handle this!"</span><span class="pun">);</span><span class="pln">
                    terminateService</span><span class="pun">.</span><span class="typ">Set</span><span class="pun">();</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">else</span><span class="pln">
            </span><span class="pun">{</span><span class="pln">
                </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Error: {0}. Resetting everything"</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">.</span><span class="typ">EventType</span><span class="pun">);</span><span class="pln">
                var port </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">SerialPort</span><span class="pun">)</span><span class="pln">sender</span><span class="pun">;</span><span class="pln">
                port</span><span class="pun">.</span><span class="typ">DiscardInBuffer</span><span class="pun">();</span><span class="pln">
                port</span><span class="pun">.</span><span class="typ">DiscardOutBuffer</span><span class="pun">();</span><span class="pln">
                unprocessedBuffer </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
                port</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> byte</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> NAK </span><span class="pun">},</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ProcessBuffer</span><span class="pun">(</span><span class="pln">byte</span><span class="pun">[]</span><span class="pln"> buffer</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> length</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="typ">List</span><span class="str">&lt;byte&gt;</span><span class="pln"> message </span><span class="pun">=</span><span class="pln"> unprocessedBuffer</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> length</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> ETX</span><span class="pun">)</span><span class="pln">
                </span><span class="pun">{</span><span class="pln">
                    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">message </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
                    </span><span class="pun">{</span><span class="pln">
                        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"MessageReceived: {0}"</span><span class="pun">,</span><span class="pln">
                                          </span><span class="typ">Encoding</span><span class="pun">.</span><span class="pln">ASCII</span><span class="pun">.</span><span class="typ">GetString</span><span class="pun">(</span><span class="pln">message</span><span class="pun">.</span><span class="typ">ToArray</span><span class="pun">()));</span><span class="pln">
                        message </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
                    </span><span class="pun">}</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> STX</span><span class="pun">)</span><span class="pln">
                message </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">message </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
                message</span><span class="pun">.</span><span class="typ">Add</span><span class="pun">(</span><span class="pln">buffer</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span><span class="pln">
            unprocessedBuffer </span><span class="pun">=</span><span class="pln"> message</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ينتظر البرنامج بالأعلى الرسائل المُضمَّنة بين بايتات <code>STX</code> و <code>ETX</code>، ثم يُرسِل النص الفعلّي إلى مَجْرى الخْرج، أي شئ آخر غيْر ذلك يتم إهماله. يُوقَف البرنامج في حالة حدوث طفحان بالمَخزَن المؤقت (buffer overflow) باستخدام التابع <code>Set</code>. أما في حالة حدوث أي أخطاء أُخرى، يُفرَّغ مَخزَني الدخْل والخْرج المؤقتين باستخدام التابعين <code>DiscardInBuffer</code> و <code>DiscardOutBuffer</code>، ثم تُنتظَر أي رسائل أُخرى.
</p>

<p>
	تُوضِح الشيفرة بالأعلى النقاط التالية:
</p>

<ul>
<li>
		قراءة مَنفَذ تَسلسُليّ بشكل غير مُتزامِن عن طريق التسجيل بالحَدَث <code>SerialPort.DataReceived</code>.
	</li>
	<li>
		مُعالجة أخطاء مَنفَذ تَسلسُليّ عن طريق التسجيل بالحَدَث <code>SerialPort.ErrorReceived</code>.
	</li>
	<li>
		تَّنفيذ لبروتوكول مَبنى على الرسائل غير النصية.
	</li>
	<li>
		قراءة جزئية للرسائل:
	</li>
	<li>
		قد يحدث ذلك؛ ربما لأن الحَدَث <code>SerialPort.DataReceived</code> قد أُثير قبل استلام المَنْفَذ للرسالة بأكملها (وفقًا لـ<code>ETX</code>)، أو ربما لأن التابع <code>SerialPort.Read(..., ..., port.BytesToRead)</code> لم يقرأ الرسالة بأكملها بل قرأ فقط جزءً منها، مما يترتب عليه عدم تَوفُّر كامل الرسالة بمَخزَن الدخْل المؤقت (input buffer). في هذه الحالة، يُنَحَّى الجزء المُستلَم غيْر المُعالَج (unprocessed) جانبًا لحين استلام بقية الرسالة.
	</li>
	<li>
		التَعامُل مع وصول أكثر من رسالة بدَفْعَة واحدة:
	</li>
	<li>
		قد يُثار الحَدَث <code>SerialPort.DataReceived</code> فقط بعدما يَستلِم عدة رسائل من الطرف الآخر.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصول 16-17-18-19-57-52 من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">950</guid><pubDate>Wed, 29 Jul 2020 13:25:43 +0000</pubDate></item><item><title>&#x627;&#x644;&#x627;&#x633;&#x62A;&#x62B;&#x646;&#x627;&#x621;&#x627;&#x62A; Exceptions &#x641;&#x64A; dot NET</title><link>https://academy.hsoub.com/programming/c-sharp/dotnet/%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AB%D9%86%D8%A7%D8%A1%D8%A7%D8%AA-exceptions-%D9%81%D9%8A-dot-net-r949/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_07/7.png.432053bf6e6813f103f99d060f84f778.png" /></p>

<h2>
	التقاط الاستثناءات Catching
</h2>

<p>
	يُمكن للشيفرة -بل يَنبغي لها- أن تُبلِّغ عن استثناءات Exceptions في بعض الظروف الاستثنائية. مثلًا:
</p>

<ul>
<li>
		مُحاولة <a href="https://msdn.microsoft.com/en-us/library/system.io.endofstreamexception(v=vs.110).aspx" rel="external nofollow">قراءة مَجْرى مقروء</a>
	</li>
	<li>
		محاولة <a href="https://msdn.microsoft.com/en-us/library/system.unauthorizedaccessexception(v=vs.110).aspx" rel="external nofollow">قراءة ملف بدون تَوفُّر صلاحيات</a> الولوج
	</li>
	<li>
		محاولة القيام بعملية غير صالحة مثل <a href="https://msdn.microsoft.com/en-us/library/system.dividebyzeroexception(v=vs.110).aspx" rel="external nofollow">القسمة على الصفر</a>
	</li>
	<li>
		حُدوث <a href="https://msdn.microsoft.com/en-us/library/system.net.webexception.aspx" rel="external nofollow">انتهاء مهلة</a> timeout أثناء تحميل ملف عبر الشبكة العنكبوتية
	</li>
</ul>
<p>
	ينبغي لمُستَدعِي ما caller التقاط catch الاستثناءات المُحتملة والتعامل معها فقط عندما:
</p>

<ul>
<li>
		يستطيع إصلاح الظرف الاستثنائي أو التعافي منه بشكل مناسب.
	</li>
	<li>
		إضافة معلومات عن السياق الذي حَدَثَ خلاله الاستثناء، قبل أن يَقوم بإعادة التبلِّيغ عنه مرة أُخْرى. (تُلْتقَط الاستثناءات المُعاد إلقائها عن طريق مُلتقِطي الاستثناءات بمُستوى أعلى بمَكْدَس الاستدعاءات call stack).
	</li>
</ul>
<p>
	إذا أردت التقاط الاستثناءات المُلقاة من شيفرة معينة، اِستخدِم الصيغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_8" style="">
<span class="kwd">try</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln"> 

</span><span class="pun">}</span><span class="pln"> 
</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ExceptionType</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln"> 

</span><span class="pun">}‎</span></pre>

<p>
	تُتضمَّن الشيفرة ذاتها داخل كتلة <code>try</code>، بينما تُتضمَّن الشيفرة المسئولة عن التقاط استثناء معين والتعامل معه بكتلة <code>catch</code> الخاصة به، كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_10" style="">
<span class="typ">Console</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"Please enter a filename: "</span><span class="pun">);</span><span class="pln">
string filename </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span><span class="pln">
</span><span class="typ">Stream</span><span class="pln"> fileStream</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    fileStream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileNotFoundException</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"File '{0}' could not be found."</span><span class="pun">,</span><span class="pln"> filename</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا يُعدّ عدم التقاط استثناء معين خطأً بالضرورة، إذا كنت تنوي التقاطه والتعامل معه بمُستوى أعلى بمَكْدَس الاستدعاءات call stack.
</p>

<h2>
	إعادة التبليغ Re-throwing
</h2>

<p>
	إذا أردت تَنفيذ أمر مُعين في حالة حدوث استثناء، ولكنك في نفس الوقت لا تستطيع إكمال تَّنفيذ الشيفرة بسبب هذا الاستثناء، فببساطة يُمكنك التقاط الاستثناء ثم إعادة التبليغ عنه بعد تَّنفيذ الأمر الذي تُريده، وبذلك سيلتقِطه مُلتقِط الاستثناءات التالي بحسب مَكْدَس الاستدعاءات call stack.
</p>

<p>
	هناك عدة طرائق لفعل ذلك، بعضها جيد والآخر سيء:
</p>

<p>
	في المثال التالي، سيُبلَّغ عن استثناء من نوع <code>DivideByZeroException</code>. تَلتقِط كتلة <code>catch</code> الاستثناء وتَستخدِم الكلمة المفتاحية <code>throw</code> -بمُفردها وبدون تحدّيد قيمة الاستثناء- لإعادة التبليغ عن الاستثناء الذي قد اِلتَقَطته للتو. تُعدّ هذه الطريقة سليمة حيث يتم فيها الاحتفاظ بتعقبات المكدس stack trace بصورة سليمة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_12" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
        var y </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// will throw a DivideByZeroException</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">DivideByZeroException</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Dividing by zero would destroy the universe."</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كالمثال السابق، تَلتقِط كتلة <code>catch</code> الاستثناء، لكن هنا تُعِيد التبليغ عنه باستخدام <code>throw ex</code>. في الواقع، رغم شيوع هذه الطريقة فهي غير سليمة؛ لأنها تُغيّر من تعقبات المكدس stack trace، التي ستُشير الآن إلى السطر الذي أعاد التبليغ عن الاستثناء بدلًا من الإشارة إلى المكان الأصلي المُتسبب به، لذلك لا تَستخدِم هذه الطريقة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_14" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
        var y </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// will throw a DivideByZeroException</span><span class="pln">

        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"The secret to life, the universe, and everything is {1}"</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"Something else horrible happened. The exception: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> ex</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">throw</span><span class="pln"> ex</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الأمثلة السابقة، أُعيدّ التبليغ عن استثناءات من نفس النوع، أما إذا أردت أن تُغيّر نوع الاستثناء مع تَضمِين الاستثناء الأصلي بداخله، استخدِم التعبير <code>throw new ExceptionType</code>. في هذه الحالة، ستُشير تعقبات المكدس stack trace إلى السطر المُتسبب بالاستثناء الخارجي. ولكن يُمكنك بسهولة استخدام الخاصية <code>InnerException</code> للولوج إلى تعقبات المكدس stack trace الخاصة بالاستثناء الداخلي والتي ستُشير إلى السطر الأصلي المُتسبب به. كالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_16" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"The secret to life, the universe, and everything is {1}"</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FormatException</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">InvalidOperationException</span><span class="pun">(</span><span class="str">"Watch your format string indexes."</span><span class="pun">,</span><span class="pln"> ex</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	ترشيح الاستثناءات
</h2>

<p>
	تُرَشَح الاستثناءات بناءً على النوع. مثلًا في المثال التالي، إذا بُلِّغ عن استثناء ما فسيتم تَّنفيذ أول كتلة <code>catch</code> مُتوافقة مع نوع الاستثناء. يُمكنك إضافة كتلة <code>catch</code> بالنهاية للتعامل مع النوع <code>Exception</code>، بحيث يُلجَئ إليها إذا لم تَتوافق معه كتلة أُخْرى أكثر تحدّيدًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_18" style="">
<span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        var x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
        var y </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> x</span><span class="pun">);</span><span class="pln"> 
        </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"The secret to life, the universe, and everything is {1}"</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">DivideByZeroException</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FormatException</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">AskTheUltimateQuestion</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تُرَشَح الاستثناءات فقط بناءً على النوع، فبدءًا من الإصدار 6 للغة c#‎، يُرشِح العَامِل <code>when</code> الاستثناءات بناءً على خاصياتها كذلك. كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_20" style="">
<span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> when </span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="typ">InnerException</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln"> </span><span class="com">// Any condition can go in here.</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُشبه ذلك استخدام جمل شرطية بداخل كتلة <code>catch</code>، لكن دون التسبب بأي تَغيِير بالمَكْدَس في حالة عدم تَحقُّق الشرط.
</p>

<h2>
	إعادة التبليغ عن استثناء بواسطة تابع آخر
</h2>

<p>
	قد تَحتاج أحيانًا إلى التقاط استثناء وإعادة التبليغ عنه بواسطة تابع أو خيط thread آخر، وفي ذات الوقت تريد أن تحتفظ برصة التتبع الأصلية. يُستخدَم التابع <code>ExceptionDispatchInfo.Capture</code> للقيام بذلك كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_22" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">System</span><span class="pun">.</span><span class="typ">Runtime</span><span class="pun">.</span><span class="typ">ExceptionServices</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">ExceptionDispatchInfo</span><span class="pln"> capturedException </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> ex</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        capturedException </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ExceptionDispatchInfo</span><span class="pun">.</span><span class="typ">Capture</span><span class="pun">(</span><span class="pln">ex</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="typ">Foo</span><span class="pun">(</span><span class="pln">capturedException</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">(</span><span class="typ">ExceptionDispatchInfo</span><span class="pln"> exceptionDispatchInfo</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// Do stuff</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">capturedException </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// Exception stack trace will show it was thrown from Main() and not from Foo()</span><span class="pln">
        exceptionDispatchInfo</span><span class="pun">.</span><span class="typ">Throw</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	استخدام كتلة <code>finally</code>
</h2>

<p>
	تُنفَّذ كتلة <code>finally {...}‎</code> دائما بغض النظر عما إذا كان قد تم التبليغ عن استثناء أم لا أثناء تَّنفيذ الشيفرة الموجودة بكتلة <code>try {...}‎</code> -يُستثني من ذلك حدوث استثناء من نوع <code>StackOverflowException</code> أو إذا اُستدْعِيَ التابع <code>Environment.FailFast()‎</code>-، لذلك هي ملائمة لتحرير أيّ موارد resources حُجزت بكتلة <code>try</code> بطريقة آمنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8382_24" style="">
<span class="typ">Console</span><span class="pun">.</span><span class="typ">Write</span><span class="pun">(</span><span class="str">"Please enter a filename: "</span><span class="pun">);</span><span class="pln">
string filename </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">ReadLine</span><span class="pun">();</span><span class="pln">
</span><span class="typ">Stream</span><span class="pln"> fileStream </span><span class="pun">=</span><span class="pln"> null</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">try</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    fileStream </span><span class="pun">=</span><span class="pln"> </span><span class="typ">File</span><span class="pun">.</span><span class="typ">Open</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">FileNotFoundException</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Console</span><span class="pun">.</span><span class="typ">WriteLine</span><span class="pun">(</span><span class="str">"File '{0}' could not be found."</span><span class="pun">,</span><span class="pln"> filename</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
finally
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">fileStream </span><span class="pun">!=</span><span class="pln"> null</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        fileStream</span><span class="pun">.</span><span class="typ">Dispose</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصل Exceptions والفصل ForEach من كتاب <a href="https://goalkicker.com/DotNETFrameworkBook/" rel="external nofollow">‎.NET Framework Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">949</guid><pubDate>Sun, 16 Aug 2020 13:07:00 +0000</pubDate></item></channel></rss>
