اشتراک‌ها
10 مثال از C# Refactoring

Though many easy-to-use resources are available to help with refactoring, you may not know about them. Check out these 10 tips to help you with efficient refactoring. 

10 مثال از C# Refactoring
نظرات مطالب
ارسال ایمیل در ASP.NET Core
ممنون از راهنمایی شما و با تشکر از تهیه سرویس‌های مفید در کتابخانه DNT

مطلب اشاره شده رو مطالعه کردم اما چند اختلاف داره با چیزی که بنده لازم دارم:
برای مثال حالتی رو در نظر بگیرید که مثلا پس از موجود شدن محصول و تغییر وضعیت اون، باید به تمام کاربرانی که درخواست اطلاع رسانی کردن برای اون محصول، ایمیل ارسال بشه و طبعا نه تعداد ایمیل‌ها مشخص هست و نه زمان دقیق این کار:

اول اینکه فرمودید ارسال ایمیل آنی است: برای یک ایمیل طبعا چنین به نظر میاد ولی برای تعداد بالای ایمیل، UI قفل میشه با استفاده از سرویس WebMailService  در کتابخانه‌ی DNT و البته برای اجتناب از این مشکل نمیشه هم که بدون await ازش استفاده کرد به خاطر نیازمندی‌های سرویس رندرویو در این کتابخانه.

دوم اینکه عنوان شده بود که سرویس هایی که به صورت بکگراند معرفی میشن غالبا غیر HTTP هستن و اما بنده به سرویس HttpContextAccessor نیاز دارم برای کار مورد نظرم و از طرفی خود شما هم در ارسال ایمیل به صورت قالب‌های از پیش تعیین شده HTML و در داخل سرویس ویورند کتابخانه DNT از HttpContextAccessor   استفاده کردید. 

سوم اینکه در این مطلب آمده بود که سرویس هایی که به صورت بکگراند معرفی میشن با اجرای برنامه، اجرا و درحافظه قرار میگیرن تا زمان خاتمه برنامه، حتی اگر کاری برای انجام نداشته باشن. در مورد مثال بالا هیچ مشخص نیست که کی به ارسال یک یا تعداد زیادی ایمیل احتیاج داریم، چرا که ممکنه محصولات مدت‌ها تغییری در وضعیتشون ایجاد نشه و طبعا در این صورت قرار دادن سرویس به صورت بکگراند در حافظه منطقی به نظر نمیاد.

چهارم اینکه در این نوع سرویس‌ها ظاهرا فقط یکبار در ابتدای برنامه متد ExecuteAsync   اجرا میشه که تعداد و نوع پارامترهای ورودیش مشخصه که فقط یک CancellationToken هست و بنابراین چطور میشه بهش اطلاع داد که چه زمانی (نه به صورت زمان بندی شده و بلکه به صورت آنی) کار مورد نظر رو انجام بده  (مثلا ارسال ایمیل از طریق سرویس  WebMailService موجود در کتابخانه DNT شما به تعدادی کاربر)

و آخر اینکه در زمان نیاز به انجام کاری، معمولا تعدادی هم پارامتر وجود داره برای انجام کار. (مثلا شناسه محصولی که تغییر وضعیت داشته جهت استخراج مشخصات کاربرانی که اطلاع رسانی این محصول رو فعال کردن). چطور این پارامتر هارو باید به سرویس بکگراند انتقال داد!!

ممنون از حوصله و راهنمایی شما.
مطالب دوره‌ها
تولید پویای کد در زمان اجرا توسط Reflection.Emit
در ادامه قصد داریم توسط امکانات Reflection به همراه کدهای IL، اشیایی را در زمان اجرا ایجاد کنیم.


Reflection چیست؟

Reflection چیزهایی هستند که با نگاه در یک آینه قابل مشاهده‌اند. در این حالت شخص می‌تواند قسمت‌های مختلف ظاهر خود را برانداز کرده یا قسمتی را تغییر دهید. اما این مساله چه ربطی به دنیای دات نت دارد؟ در دات نت با استفاده از Reflection می‌توان به اطلاعات اشیاء یک برنامه‌ی در حال اجرا دسترسی یافت. برای مثال نام کلاس‌های مختلف آن چیست یا درون کلاسی خاص، چه متدهایی قرار دارند. همچنین با استفاده از Reflection می‌توان رفتارهای جدیدی را نیز به کلاس‌ها و اشیاء افزود یا آن‌ها را تغییر داد.
همواره عنوان می‌شود که از Reflection به دلیل سربار بالای آن پرهیز کنید و تنها از آن به عنوان آخرین راه حل موجود استفاده نمائید و این دقیقا موردی است که در مباحث جاری بیشتر از آن استفاده خواهد شد: ساخت اشیاء جدید در زمان اجرا به کمک کدهای IL و امکانات Reflection


نگاهی به امکانات متداول Reflection

در مثال بعد، نگاهی خواهیم داشت به امکانات متداول Reflection، مانند دسترسی به متدها و خواص یک کلاس و تعویض مقدار یا فراخوانی آن‌ها:
using System;

namespace FastReflectionTests
{
    class Person
    {
        public string Name { set; get; }

        public string Speak()
        {
            return string.Format("Hello, my name is {0}.", this.Name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //روش متداول
            var vahid = new Person { Name = "Vahid" };
            Console.WriteLine(vahid.Speak());

            var type = vahid.GetType();

            //نمایش متدهای یک کلاس
            var methods = type.GetMethods();
            foreach (var method in methods)
            {
                Console.WriteLine(method.Name);
            }

            //تغییر مقدار یک خاصیت
            var setNameMethod = type.GetMethod("set_Name");
            setNameMethod.Invoke(obj: vahid, parameters: new[] { "Ali" });

            //فراخوانی یک متد
            var speakMethod = type.GetMethod("Speak");
            var result = speakMethod.Invoke(obj: vahid, parameters: null);
            Console.WriteLine(result);
        }
    }
}
با خروجی ذیل
 Hello, my name is Vahid.
set_Name
get_Name
Speak
ToString
Equals
GetHashCode
GetType
Hello, my name is Ali.
توضیحات:
در اینجا یک کلاس شخص با خاصیت نام او تعریف شده است؛ به همراه متدی که رشته‌ای را نمایش خواهد داد.
در متد Main برنامه، ابتدا یک وهله جدید از این شخص ایجاد شده و سپس به روش متداول، متد Speak آن فراخوانی گردیده است. در ادامه کار از امکانات Reflection برای انجام همین امور کمک گرفته شده است.
کار با دریافت نوع یک وهله شروع می‌شود. برای نمونه در اینجا توسط vahid.GetType به نوع وهله ساخته شده دسترسی یافته‌ایم. سپس با داشتن این type، می‌توان به کلیه امکانات Reflection دسترسی یافت. برای مثال توسط GetMethods، لیست کلیه متدهای موجود در کلاس شخص بازگشت داده می‌شود.
اگر به خروجی فوق دقت کنید، پس از سطر اول، 7 سطر بعدی نمایانگر متدهای موجود در کلاس شخص هستند. شاید عنوان کنید که این کلاس به نظر یک متد بیشتر ندارد. اما در دات نت اشیاء از شیء Object مشتق می‌شوند و چهار متد ToString، Equals، GetHashCode و GetType متعلق به آن هستند. همچنین خواص تعریف شده نیز در اصل به دو متد set و get به صورت خودکار در کدهای IL برنامه ترجمه خواهند شد. از همین متد set_Name در ادامه برای مقدار دهی خاصیت نام وهله ایجاد شده استفاده شده است.
همانطور که ملاحظه می‌کنید برای فراخوانی یک وهله از طریق Reflection، ابتدا توسط متد type.GetMethod می‌توان به آن دسترسی یافت و سپس با فراخوانی متد Invoke، می‌توان متد مدنظر را بر روی یک شیء مهیا با پارامترهایی که ذکر می‌کنیم، فراخوانی کرد. اگر این متد پارامتری ندارد، آن‌را نال قرار خواهیم داد.

تا اینجا مقدمه‌ای را ملاحظه نمودید که بیشتر جهت تکمیل بحث، حفظ روابط منطقی قسمت‌های مختلف آن و یادآوری مباحث مرتبط با Reflection ذکر شدند.


ایجاد اشیاء در زمان اجرای برنامه

یکی از کلاس‌های مهم Reflection که در منابع مختلف کمتر به آن پرداخته شده است، کلاس DynamicMethod آن است که از آن می‌توان برای ایجاد اشیاء و یا متدهایی پویا در زمان اجرا استفاده کرد. این کلاس قرار گرفته در فضای نام System.Reflection.Emit، دارای یک ILGenerator است که می‌توان به آن OpCodeهایی را اضافه کرد. زمانیکه کار ایجاد این متدپویا به پایان رسید، با استفاده از Delegates امکان دسترسی و اجرای این متد پویا وجود خواهد داشت.
یک مثال کامل را در این زمینه در ادامه ملاحظه می‌نمائید:
using System;
using System.Reflection.Emit;

namespace FastReflectionTests
{
    class Program
    {
        static double Divider(int a, int b)
        {
            return a / b;
        }

        delegate double DividerDelegate(int a, int b);
        static void Main(string[] args)
        {
            //روش متداول
            Console.WriteLine(Divider(10, 2));

            //تعریف امضای متد
            var myMethod = new DynamicMethod(
                                        name: "DividerMethod",
                                        returnType: typeof(double),
                                        parameterTypes: new[] { typeof(int), typeof(int) },
                                        m: typeof(Program).Module);
            //تعریف بدنه متد
            var il = myMethod.GetILGenerator();
            il.Emit(opcode: OpCodes.Ldarg_0); //بارگذاری پارامتر اول بر روی پشته ارزیابی
            il.Emit(opcode: OpCodes.Ldarg_1); //بارگذاری پارامتر دوم بر روی پشته ارزیابی
            il.Emit(opcode: OpCodes.Div); // دو پارامتر از پشته ارزیابی دریافت و تقسیم خواهند شد
            il.Emit(opcode: OpCodes.Ret); // دریافت نتیجه نهایی از پشته ارزیابی و بازگشت آن

            //فراخوانی متد پویا
            //روش اول
            var result = myMethod.Invoke(obj: null, parameters: new object[] { 10, 2 });
            Console.WriteLine(result);

            //روش دوم
            var method = (DividerDelegate)myMethod.CreateDelegate(delegateType: typeof(DividerDelegate));
            Console.WriteLine(method(10, 2));
        }
    }
}
توضیحات
در ابتدای این مثال جدید یک متد متداول تقسیم کننده دو عدد را ملاحظه می‌کنید. در ادامه قصد داریم overload دیگری از این متد را توسط کدهای MSIL در زمان اجرا ایجاد کنیم که دو پارامتر int را قبول می‌کند.
کار با وهله سازی کلاس DynamicMethod موجود در فضای نام System.Reflection.Emit شروع می‌شود. در اینجا کار تعریف امضای متد جدید باید صورت گیرد. برای مثال نام آن چیست، نوع خروجی آن کدام است. نوع پارامترهای آن چیست و نهایتا این متدی که قرار است به صورت پویا به برنامه اضافه شود، باید در کجا قرار گیرد. برای اینکار از Module خود کلاس Program برنامه استفاده شده است.
پس از تعریف امضای متد پویا، نوبت به تعریف بدنه‌ی آن می‌رسد. کار با دریافت یک ILGenerator که می‌توان در آن کدهای IL را وارد کرد شروع می‌شود. مابقی آن تعریف کدهای IL توسط متد Emit است و پیشتر با مقدمات اسمبلی دات نت در قسمت‌های قبلی مبحث جاری آشنا شده‌ایم. ابتدا دو Ldarg فراخوانی شده‌اند تا دو پارامتر ورودی متد را دریافت کنند. سپس Div بر روی آن‌ها صورت گرفته و نهایتا نتیجه بازگشت داده شده است.
خوب؛ تا اینجا موفق شدیم اولین متد پویای خود را ایجاد نمائیم. برای اجرا آن حداقل دو روش وجود دارد:
الف) فراخوانی متد Invoke بر روی آن. با توجه به اینکه قرار نیست این متد بر روی وهله‌ی خاصی اجرا شود، اولین پارامتر آن null وارد شده است و سپس پارامترهای این متد پویا توسط آرگومان دوم متد Invoke وارد شده‌اند.
ب) می‌توان این عملیات را اندکی شکیل‌تر کرد. برای اینکار پیش از متد Main برنامه یک delegate به نام DividerDelegate تعریف شده است. سپس با استفاده از متد CreateDelegate، خروجی این متد پویا را تبدیل به یک delegate کرده‌ایم. اینبار فراخوانی متد پویا بسیار شبیه به متدهای معمولی می‌شود.
بازخوردهای پروژه‌ها
پر نکردن فیلد های PDF با استفاده از iTextSharp
من با استفاده از این مثال   اینجا  یک  PDF درست کردم بعد  هر بار تلاش برای تغییر داده‌های Text Box میکنم یا خالی ذخیره میکند.

using System;
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace Delete
{
class Program
{
//روش صحیح ثبت و معرفی فونت در این کتابخانه
public static iTextSharp.text.Font GetTahoma()
{
var fontName = "Tahoma";
if (!FontFactory.IsRegistered(fontName))
{
var fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
FontFactory.Register(fontPath);
}
return FontFactory.GetFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
}

static void Main(string[] args)
{
string fileNameExisting = @"name.pdf";
string fileNameNew = @"newform.pdf";

using (var existingFileStream = new FileStream(fileNameExisting, FileMode.Open))
using (var newFileStream = new FileStream(fileNameNew, FileMode.Create))
{
var pdfReader = new PdfReader(existingFileStream);
using (var stamper = new PdfStamper(pdfReader, newFileStream))
{
//نکته مهم جهت کار با اطلاعات فارسی
//در غیراینصورت شاهد ثبت اطلاعات نخواهید بود
stamper.AcroFields.AddSubstitutionFont(GetTahoma().BaseFont);

//form.Fields.Keys = تمام فیلدهای موجود در فرم
var form = stamper.AcroFields;

//مقدار دهی فیلدهای فرم
form.SetField("name3", "مقدار1");
form.SetField("name2", "مقدار2");

// "Yes" and "Off" are valid values here
//form.SetField("Check Box 1", "Yes");

// "" and "Off" are valid values here
//form.SetField("Option Button 1", "");

// نحوه مقدار دهی لیست
//form.SetListOption("ListBox1", new[] { "1مقدار یک", "مقدار دو1" }, null);
//form.SetField("ListBox1", null);

// به این ترتیب فرم دیگر توسط کاربر قابل ویرایش نخواهد بود
//stamper.PartialFormFlattening --> جهت غیرقابل ویرایش نمودن فیلدی مشخص
stamper.FormFlattening = true;

stamper.Close();
pdfReader.Close();
}
}

//Process.Start("newform.pdf");
}
}
}
با توجه به این کد خروجی که میدهد این است :

که اگر بخوام این مشکل را بر طرف بشه کافی:

به جای این کد

PdfStamper pdfStamper = new PdfStamper(pdfReader, stream);
این کد را وارد کنیم
PdfStamper stamper = new PdfStamper(pdfReader, stream, '\0', true);
که در این صورت این کد
pdfStamper.FormFlattening = false;
 این صورت باید بشود و در این حالت کاربر میتواند تغییر دهد.

من برای ایجاد هدر سفارشی میخواستم از این مثال استفاده کنم تا فیلد هایی را پر کند از مثال‌های مشابه اون نتیجه دلخواه رو نگرفتم


نظرات مطالب
مقدمه‌ای بر داکر، قسمت سوم
من دستور زیر را اجرا میکنم 
docker build -f Dockerfile -t alikhll/testasp1 . 
Step 5/7 : RUN npm i
 ---> [Warning] The requested image's platform (linux/amd64) does not match the detected host platform (windows/amd64) and no specific platform was requested
 ---> Running in dc37481d5781

added 48 packages, and audited 49 packages in 6s

found 0 vulnerabilities
npm notice
npm notice New minor version of npm available! 8.5.5 -> 8.7.0
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v8.7.0>
npm notice Run `npm install -g npm@8.7.0` to update!
npm notice
The command '/bin/sh -c npm i' returned a non-zero code: 4294967295: failed to shutdown container: container dc37481d5781615dbf01c129f2322f06fcac8851a8a4078a6273438a8427254a encountered an error during hcsshim::System::waitBackground: failure in a Windows system call: The virtual machine or container with the specified identifier is not running. (0xc0370110): subsequent terminate failed container dc37481d5781615dbf01c129f2322f06fcac8851a8a4078a6273438a8427254a encountered an error during hcsshim::System::waitBackground: failure in a Windows system call: The virtual machine or container with the specified identifier is not running. (0xc0370110)
کلا هر دستور npm که اجرا میکنم خطای بالا رو میده
توی پوشه اش کامند npm i  اجرا میکنم درست کار میکنه و پکیچ‌ها نصب میشه ولی داخل محیط داکر خیر
از docker desktop و ویندوز 10 استفاده میکنم
پکیج نود هم از داکر دانلود و نصب کردم
نظرات مطالب
اجرای کد از راه دور
سعی و خطای جدیدی که لاگ شده:
path : \dompdf\dompdf.php
QUERY_STRING  input_file=http://miroslavmorant.com/tutoriales/wp-content/plugins/contact-form-7/images/id.flv???
نتیجه: فایل dompdf.php نیز احتمالا مشکل امنیتی دارد. بررسی کنید.
نظرات مطالب
کمی درباره httpmodule
بله. در جدولی که تهیه کردند این مورد دقیقا ذکر شده:
«AcquireRequestState : این قسمت برای مدیریت state می‌باشد مثلا مدیریت session ها»
به این معنا که سشن در تمام رویدادگردان‌های آن مهیا نیست. فقط تعدادی از آن‌ها دسترسی به سشن دارند. برای مثال:
    public class SimpleModule : IHttpModule  
    {  
        void IHttpModule.Init(HttpApplication application)  
        {  
            application.BeginRequest += new System.EventHandler(BeginRequest);  
            application.AcquireRequestState += new EventHandler(application_AcquireRequestState);  
        }  

        public void BeginRequest(object sender, EventArgs e)  
        {  
            // no session here
        }  

        void application_AcquireRequestState(object sender, EventArgs e)  
        {  
            HttpApplication app = sender as HttpApplication;  
            app.Session.Add("Message", "hello module");      
        }  

        public void Dispose()  
        {  
        }  
    }
اشتراک‌ها
معرفی سایت fuget.org

a new site for browsing nuget packages. It is my best attempt to build a tool to help you both discover new packages and to dig in deep to learn them once found.


معرفی سایت fuget.org