مطالب
استفاده از ماژول Remote
همانطور که در مقاله «آغاز کار با الکترون» گفتیم، فرآیند اصلی، تنها فرآیندی است که توانایی استفاده از گرافیک بومی سیستم عامل را دارد. ولی بسیاری از اوقات نیاز است در سمت renderProcess توانایی انجام این کار‌ها را داشته باشیم. در این مقاله قصد داریم که همان دیالوگ‌های open و save را از طریق Render Process اجرا نماییم.
الکترون برای اینکار از یک ماژول به نام remote استفاده می‌کند که وظیفه آن برقراری ارتباط IPC از Render Process به Main Process است و مواردی را که لازم است، در اختیار شما قرار می‌دهد. در این شیوه لازم نیست شما مرتبا به ارسال پیام بپردازید، بلکه این ارتباطات را ماژول remote فراهم می‌کند. این مورد شبیه به سیستم RMI در جاواست.

برای استفاده از remote در فایل html، کدهای زیر را در تگ اسکریپت اضافه می‌کنیم:
  const remote=require("electron").remote;
    const dialog=remote.dialog;
اینبار هم مانند قسمت قبلی، کدها را به شیوه دیگری انتساب دادیم. قصد ما از تغییر این رویه این است که با انواع حالت‌های انتساب اشیاء، آشنا شویم. بعد از آن توابع زیر را اضافه می‌کنیم:
  function OpenDialog()
    {
      dialog.showOpenDialog({
        title:'باز کردن فایل متنی',
         properties: [ 'openFile']//[ 'openFile', 'openDirectory', 'multiSelections' ]
        ,filters:[
        {name:'فایل‌های نوشتاری' , extensions:['txt','text']},
        {name:'جهت تست' , extensions:['doc','docx']}
         ]
      },
        (filename)=>{
          if(filename===undefined)
             return;
             var content=  fs.readFileSync(String(filename),'utf8');
             document.getElementById("TextFile").value=content;
    });
    }

    function SaveDialog()
    {
      dialog.showSaveDialog({
        title:'باز کردن فایل متنی',
         properties: [ 'openFile']//[ 'openFile', 'openDirectory', 'multiSelections' ]
        ,filters:[
        {name:'فایل‌های نوشتاری' , extensions:['txt','text']}
         ]
      },
        (filename)=>{
          if(filename===undefined)
             return;
             var content=document.getElementById("TextFile").value;
             fs.writeFileSync(String(filename),content,'utf8');
       });
    }
برای استفاده از این توابع، کدهای زیر را نیز به فایل اضافه می‌کنیم تا دکمه‌های open و save به صفحه اضافه شوند:
<button onclick="OpenDialog();" > Open File</button>
<button onclick="SaveDialog();" > Save File</button>
حالا برنامه را اجرا و تست کنید.

عبارت remote شامل متدهای فراوانی است که تعدادی از آن‌ها را بر می‌شماریم:
remote.getCurrentWindow()
شیء BrowserWindow صفحه جاری را باز می‌گرداند.

remote.getCurrentWebContents()
شیء webContents صفحه جاری را باز می‌گرداند.

remote.getGlobal(name)
این متد، دسترسی به شیء global را داراست و یکی از اشیاء ارتباطی بین Main Process و RenderProcess است که می‌تواند هر نوع داده‌ای را جابجا نماید. برای مشاهده بهتر از نحوه کارکرد این متد کد زیر را مشاهده نمایید:
Main Process
global.testData={year:1395};

Render Process
alert(remote.getGlobal("testData").year);
از این پس هر موقع renderProcess به این کد برسد، پیام 1395 را روی صفحه نمایش خواهد داد.

remote.process
شیء، process را از main process دریافت می‌کند و با کد زیر برابر است. ولی مزیت این متد این است که از کش نیز استفاده می‌نماید.
remote.getGlobal('process')

در مورد شیء process باید گفت که شامل خصوصیات و متدهایی در مورد پروسه اصلی اپلیکیشن می‌باشد. این اطلاعات مثل دریافت شماره نسخه الکترون، شماره نسخه کرومیوم، دریافت اطلاعات حافظه در مورد پروسه اپلیکیشن و حتی دریافت اطلاعات حافظه در مورد کل سیستم و ... می‌شود.
نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 2 - بررسی ساختار جدید Solution
یک نکته‌ی تکمیلی در مورد نصب نگارش‌های جدید NET Core.

پس از نصب به روز رسانی‌های NET Core.، دستور ذیل را در خط فرمان اجرا کنید:
> dotnet --version
1.0.0-preview2-003131
حاصل آن، عبارتی است که در فایل global.json درج خواهد شد. پس از این تغییر:
{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-preview2-003131"
  }
}
نیاز است یکبار Solution را بسته و مجددا باز کنید. پس از آن به صورت خودکار، بازیابی بسته‌های مرتبط شروع می‌شوند.
به علاوه تنها در این حالت است که اگر به برگه‌ی Updates نیوگت مراجعه کنید، به روز رسانی‌های جدید را مشاهده خواهید کرد:



بنابراین تازمانیکه فایل global.json را با شماره‌ی SDK جدید به روز رسانی نکنید، نیوگت، بسته‌های به روز شده‌ی مرتبط را دریافت نخواهد کرد.

به علاوه اگر Solution شما دارای چندین پروژه است، بهتر است دستور ذیل را در کنسول پاورشل نیوگت وارد کنید تا تمام آن‌ها را به یکباره به روز رسانی کند:
PM> update-package
پس از آن اگر خطای ذیل را دریافت کردید:
Can not find runtime target for framework '.NETCoreApp,Version=v1.0' compatible with one of the target runtimes: 'win10-x64, win81-x64, win8-x64, win7-x64'
در فایل‌های project.json، سطر ناقص ذیل را یافته:
"Microsoft.NETCore.App": "vX",
و آن‌را به مدخل کامل ذیل تبدیل کنید:
"Microsoft.NETCore.App": {
      "version": "vX",
      "type": "platform"
    },
مطالب
امکان تعریف ویژگی‌ها بر روی توابع محلی در C# 9.0

یکی از ویژگی‌های جدید اضافه شده به سی شارپ 9، Attributes on local functions نام دارد و این توانایی را به ما می‌دهد تا بر روی متد‌های محلی که درون متدها تعریف می‌شوند، Attributes قرار دهیم. قابلیت local functions در نسخه 7 سی شارپ اضافه شده‌است و با استفاده از این قابلیت می‌توانیم درون یک متد، تابع دیگری را تعریف کنیم و در همان متد، از آن تابع درونی استفاده کنیم. در واقع تابع درونی، لوکال متد بیرونی است و در خارج از متد بیرونی، قابل دسترسی نیست. مانند مثال زیر:

    // Main method 
    public static void Main()
    {
        // Local Function 
        void AddValue(int a, int b)
        {
            Console.WriteLine("Value of a is: " + a);
            Console.WriteLine("Value of b is: " + b);
            Console.WriteLine("Sum of a and b is: {0}", a + b);
            Console.WriteLine();
        }

        // Calling Local function 
        AddValue(20, 40);
        AddValue(40, 60);
    }

برای بررسی این ویژگی جدید سی شارپ 9.0، از یک مثال استفاده می‌کنیم. فرض کنید یک برنامه‌ی کنسول را داریم و می‌خواهیم یک قطعه کد فقط در حالتی در خروجی نوشته شود که برنامه در حالت دیباگ اجرا شده باشد و اگر در حالت ریلیز باشد، در خروجی مشاهده نشود. قبل از نسخه‌ی 9.0 سی شارپ، مجبور هستیم از directive های کامپایلر زبان استفاده کنیم و از طریق آن به کامپایلر بفهمانیم که چه زمانی این قطعه کد را کامپایل کند. مانند مثال زیر:

        static void Main(string[] args)
        {
            static void DoAction()
            {
                // DoAction

                Console.WriteLine("DoAction...");
            }

#if DEBUG
            DoAction();
#endif
        }

اما با استفاده قابلیت اضافه شده‌ی در این نسخه از سی شارپ، می‌توان روی متدهای محلی هم Attributes اضافه کرد. پس می‌توانیم از ConditionalAttribute استفاده کنیم و آن را در بالای متد محلی قرار دهیم و از کامپایلر بخواهیم در حالت دیباگ اجرا شود. مانند کد زیر

        static void Main(string[] args)
        {
            [Conditional("DEBUG")]
            static void DoAction()
            {
                // Do Action Here

                Console.WriteLine("Do Action...");
            }

            DoAction();
        }

اگر بر روی متدهای محلی C# 8.0 از Attribute استفاده کنیم، با خطای زیر روبرو می‌شویم:

ErrorCS8400Feature 'local function attributes' is not available in C# 8.0. Please use language version 9.0 or greater.
نظرسنجی‌ها
به روز رسانی‌های برنامه‌های خود را چگونه ارائه می‌کنید؟
به روز رسانی خودکار برنامه توسط خود آن (self-update) با بررسی اطلاعات آخرین به روز رسانی، از وب‌سایت ما.
کاربر نگارش‌های جدید دریافتی را (از طریق ایمیل و یا وب سایت ما) بر روی نگارش‌های فعلی کپی می‌کند.
کاربر یک برنامه‌‌ی به روز رسانی نصاب مانند را اجرا می‌کند.
کاربران به علت پیچیدگی برنامه نمی‌توانند برنامه را به روز رسانی کنند؛ ما برای آن‌ها اینکار را انجام می‌دهیم.
از ClickOnce استفاده می‌کنیم.
توسط سیستم به روز رسانی App Storeها.
از Docker استفاده می‌کنیم.
مطالب
تبادل داده ها بین لایه ها- قسمت اول

معماری لایه بندی شده، یک معماری بسیار همه گیر می‌باشد. به این خاطر که به راحتی SOC ، decoupling و قدرت درک کد را بسیار بالا می‌برد. امروزه کمتر برنامه نویس و فعال حوضه‌ی نرم افزاری است که با لایه‌های کلی و وظایف آنها آشنا نباشد ( UI layer آنچه که ما می‌بینیم، middle layer   برای مقاصد منطق کاری، data access layer برای هندل کردن دسترسی به داده‌ها). اما مسئله ای که بیشتر برنامه نویسان و توسعه دهندگان نرم افزار با استاندارد‌های آن آشنا نیستند، راه‌های تبادل داده‌ها مابین layer ‌ها می‌باشد. در این مقاله سعی داریم راه‌های تبادل داده‌ها را مابین لایه‌ها، تشریح کنیم. 

Layers  و Tiers با هم متفاوت هستند

Layer  با Tier متفاوت است. هنگامیکه در مورد مفهوم layer و Tier دچار شک شدید، دیاگرام ذیل می‌تواند به شما بسیار کمک کند. layer به مجزاسازی منطقی کد و Tier هم به مجزا سازی فیزیکی در ماشین‌های مختلف اطلاق می‌شود. توجه داشته باشید که این نکته یک شفاف سازی کلی در مورد یک مسئله مهم بود.


داده‌های وارد شونده( incoming ) و خارج شونده( outgoing )

ما باید تبادل داده‌ها را از دو جنبه مورد بررسی قرار دهیم؛ اول اینکه داده‌ها چگونه به سمت لایه Data Access می‌روند، دوم اینکه داده‌ها چگونه به لایه UI پاس می‌شوند، در ادامه شما دلیل این مجزا سازی را درک خواهید کرد. 

روش اول: Non-uniform

این روش اولین روش و احتمالا عمومی‌ترین روش می‌باشد. خوب، اجازه دهید از لایه‌ی UI به لایه DAL شروع کنیم. داده‌ها از لایه UI به Middle با استفاده از getter ‌ها و setter ‌ها ارسال خواهد شد. کد ذیل این مسئله را به روشنی نمایش می‌دهد.

Customer objCust = new Customer();
objCust.CustomerCode = "c001";
objCust.CustomerName = "Shivprasad";

بعد از آن، از لایه Middle  به لایه Data Access داده‌ها با استفاده از مجزاسازی به وسیله comma و آرایه‌ها و سایر روش‌های  non-uniform پاس داده می‌شوند. در کد ذیل به متد Add دقت کنید که چگونه فراخوانی به لایه Data Access را با استفاده از پارامتر‌های ورودی انجام می‌دهد. 

public class Customer
{
    private string _CustomerName = "";
    private string _CustomerCode = "";
    public string CustomerCode
    {
        get { return _CustomerCode; }
        set { _CustomerCode = value; }
    }
    public string CustomerName
    {
        get { return _CustomerName; }
        set { _CustomerName = value; }
    }
    public void Add()
    {
        CustomerDal obj = new CustomerDal();
        obj.Add(_CustomerName,_CustomerCode);
    }
}

کد ذیل، متد add در لایه Data Access را با استفاده از دو متد نمایش می‌دهد. 

public class CustomerDal
{
    public bool Add(string CustomerName,string CustomerCode)
    {
        // Insert data in to DB
    }
}

بنابراین اگر بخواهیم  به صورت خلاصه نحوه پاس دادن داده‌ها را در روش non-uniform  بیان کنیم، شکل ذیل به زیبایی این مسئله را نشان می‌دهد. 

· از لایه UI به لایه Middle  با استفاده از setter و getter

· از لایه Middle به لایه  data access با استفاده از comma ، input ، array 

حال نوبت این است بررسی کنیم که چگونه داده‌ها از DAL به UI   در روش non-uniform پاس خواهند شد. بنابراین اجازه دهید که اول از UI شروع کنیم. از لایه UI داده‌ها با استفاده از object ‌های لایه Middle  واکشی می‌شوند.   

Customer obj = new Customer();
List<Customer> oCustomers = obj.getCustomers();

از لایه Middle هم داده‌ها با استفاده از dataset ، datatable و xml پاس خواهند شد. مهمترین مسئله برای لایه middle ، loop بر روی dataset و تبدیل آن به strong type object  ها می‌باشد. برای مثال می‌توانید کد تابع getCustomers که بر روی dataset ، loop می‌زند و یک لیست از Customer ‌ها را آماده می‌کند در ذیل مشاهده کنید. این تبدیل باید انجام شود، به این دلیل که UI به کلاس‌های strongly typed دسترسی دارد. 

public class Customer
{
    private string _CustomerName = "";
    private string _CustomerCode = "";
    public string CustomerCode
    {
        get { return _CustomerCode; }
        set { _CustomerCode = value; }
    }
    public string CustomerName
    {
        get { return _CustomerName; }
        set { _CustomerName = value; }
    }
    public List<Customer> getCustomers()
    {
        CustomerDal obj = new CustomerDal();
        DataSet ds = obj.getCustomers();
        List<Customer> oCustomers = new List<Customer>();
        foreach (DataRow orow in ds.Tables[0].Rows)
        {
            // Fill the list
        }
        return oCustomers;
    }
}

با انجام این تبدیل به یکی از بزرگترین اهداف معماری لایه بندی شده می‌رسیم؛ یعنی اینکه « UI نمی‌تواند به طور مستقیم به کامپوننت‌های لایه Data Access مانند ADO.NET ، OLEDB و غیره دستیابی داشته باشد. با این روش اگر ما در ادامه متدولوژی Data Access را تغییر دهیم تاثیری بر روی لایه UI نمی‌گذارد.» آخرین مسئله اینکه کلاس CustomerDal یک Dataset  را با استفاده از ADO.NET بر می‌گرداند و Middle از آن استفاده می‌کند. 

public class CustomerDal
{
    public DataSet getCustomers()
    {
        // fetch customer records
        return new DataSet();
    }
}

حال اگر بخواهیم حرکت داده‌ها را به لایه UI، به صورت خلاصه بیان کنیم، شکل ذیل کامل این مسئله را نشان می‌دهد. 

· داده‌ها از لایه DAL به لایه  Middle با استفاده از Dataset ، Datareader ،  XML ارسال خواهند شد. 

· از لایه Middle به UI  از strongly typed classes استفاده می‌شود. 


مزایا و معایب روش non-uniform

یکی از مزایای non-uniform

· به راحتی قابل پیاده سازی می‌باشد، در مواردی که روش data access تغییر نمی‌کند این روش کارآیی لازم را دارد.

تعدادی از معایب  این روش

· به خاطر اینکه یک ساختار uniform نداریم، بنابراین نیاز داریم که همیشه در هنگام عبور از یک لایه به یک لایه‌ی دیگر از یک ساختار به یک ساختار دیگر تبدیل را انجام دهیم.

· برنامه نویسان از روش‌های خودشان برای پاس دیتا استفاده می‌کنند؛ بنابراین این مسئله خود باعث پیچیدگی می‌شود.

· اگر برای مثال شما بخواهید متدولوژی Data Access خود را تغییر دهید، تغییرات بر تمام لایه‌ها تاثیر می‌گذارد. 

نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 7 - کار با فایل‌های config
منظور این بود که اگر فایل متنی JSON مرتبط را در نوت‌پد (و امثال آن و یا با برنامه نویسی) باز کردید و تغییر دادید (ذخیره کردید، تاریخ Last modified آن را تغییر دادید)، بلافاصله تغییرات آن در برنامه منعکس می‌شوند؛ چون یک file watcher برای تغییرات آن فایل در پشت صحنه فعال است. مانند file watcher فایل معروف web.config در برنامه‌های ASP.NET که آن هم یک کانفیگ است البته از نوع XML و اگر تغییری در آن داده شود، کل برنامه را ری‌استارت می‌کند. اما در اینجا برنامه با تغییرات فایل JSON کانفیگ آن ری‌استارت نخواهد شد. فقط «یک نکته: بارگذاری مجدد اطلاعات فایل config در ASP.NET Core 1.1» قابل استفاده خواهد بود.
ایجاد رابط کاربری هم برای آن مساله‌ای است شخصی که در نهایت شامل deserialization و تبدیل آن به شیء و تغییر آن در برنامه و در آخر serialization این شیء و بازگشت به حالت JSON آن است. عموما از کتابخانه‌ی JSON.NET برای انجام اینکار استفاده می‌کنند.
نظرات اشتراک‌ها
#C برای برنامه نویسی سیستمی
نسخه native، منظور کامپایل مستقیم کدهای سی‌شارپ به کدهای ماشین هستند. در حال حاضر اگر صحبت از #C می‌شود، منظور #CLR C است. یعنی کدهای شما ابتدا به IL ترجمه می‌شوند و بعد IL توسط JIT Compiler به کدهای ماشین ترجمه خواهد شد. در نسخه native این دو مرحله حذف و تبدیل به یک مرحله خواهند شد. البته برای مقاصد سیستمی جهت دسترسی بیشتر به سخت افزار و همچنین بالابردن سرعت اجرایی کدها. برای رقابت با ++C با ارائه زبانی که type safe است؛ برای کارهای async بهینه سازی شده‌است، سرعت توسعه با آن بالاتر است و ابزارهای بهتری برای آن تدارک دیده شده‌اند. ضمنا استاندارد آن در اختیار مایکروسافت است و تغییرات آتی آن ساده‌تر خواهند بود و سریعتر.
پاسخ به بازخورد‌های پروژه‌ها
بروز خطا
- نگارش 2.8، برای iTextSharp 5.5.6 تهیه نشده‌است. برای نگارش 5.5.5 آن کامپایل شده‌است. در یک چنین مواردی راه حل «به روز رسانی قسمت assemblyBinding فایل‌های config توسط NuGet» می‌تواند مفید باشد.
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="itextsharp" publicKeyToken="8354ae6d2174ddca" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.5.6.0" newVersion="5.5.6.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
- همچنین بسته‌ی نیوگت این کتابخانه برای iTextSharp 5.5.6 به روز شد. بنابراین دستور ذیل را صادر کنید:
PM> update-package
مطالب
چگونه نرم افزارهای تحت وب سریعتری داشته باشیم؟ قسمت دوم
قسمت اول 

4. فشرده سازی HTTP را فعال کنید
اطمینان حاصل کنید که HTTP Compression در تمامی بخش‌های اصلی برنامه شما فعال است. حداقل کاری که می‌توانید در این رابطه بکنید این است که خروجی HTML که توسط برنامه شما تولید می‌شود را فشرده سازی کنید. جهت فعال سازی فشرده سازی در برنامه خود بهتر است در اولویت اول از ماژول ویژه ای که جهت این کار در IIS در نظر گرفته شده استفاده کنید. این ماژول تمامی کارها را به صورت خودکار برای شما انجام می‌دهد. اگر دسترسی به IIS جهت فعال سازی آن را ندارید، می‌توانید از ماژول‌های ASP.NET که جهت این کار تهیه شده استفاده کنید. می‌توانید کمی جستجو کنید و یا خودتان یکی تهیه کنید!

5.تنظیم CacheControlMaxAge
مقدار CacheControlMaxAge را در فایل web.config را طوری تنظیم کنید تا هیچ کاربری هیچ فایل static را دیگر درخواست نکند. مثلا می‌توانید این مقدار را بر روی چند ماه تنظیم کنید و البته فراموش نکنید این مقدار را در صفحات پویای خود بازنویسی (override) کنید تا مشکلی در رابطه با کش شدن فرم‌های اصلی برنامه (همانطور که در نکته اول بخش اول ذکر شد) پدید نیاید. البته کش کردن فایل‌های استاتیک برنامه بار مالی نیز برای شما و کاربرانتان خواهد داشت. دیگر هزینه پهنای باند اضافی جهت دانلود این فایل‌ها در هر درخواست برای شما (در سمت سرور) و کاربرانتان (در سمت کاربر) پرداخت نخواهد شد!

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

7. بهره برداری از ORM Profiler
ORM Profiler ها تمامی فعالیت‌های ORM تحت نظر گرفته، دستورات T-SQL ارسالی به بانک اطلاعاتی را واکشی کرده و برای شما نمایش می‌دهند. تعدادی از آنها نیز این دستورات را آنالیز کرده پیشنهاداتی در رابطه با بهبود کارایی به شما ارائه می‌دهند. برای مثال به جای اینکه شما 2000 رکورد را یکی یکی از بانک بازیابی کنید، می‌توانید آن را به صورت یک query به بانک ارسال کنید. این موضوع به سادگی توسط ORM Profiler‌ها قابل بررسی است. نمونه ای از این نرم افزارها را می‌توانید در این سایت یا این سایت   پیدا کنید. البته در صورتی که نمی‌خواهید از نرم افزارهای جانبی استفاده کنید، می‌توانید از ابزارهای توکار بانک‌های اطلاعاتی مانند SQL Profiler نیز استفاده کنید (راهنمایی).