نظرات مطالب
EF Code First #2
با سلام (چند سوال)
۱- زمانی که ef کار میکردم اگه میومدیم تیبل درست میکردیم وداخل مثلا۳۰۰ رکورد بود اگه وسط کار این جدوال تغییرات لازم داشت دوباره اسکریپت میگرفتیم تمامی رکوردها حذف و دوبار جدوال ساخته میشد این مشکل در ef حل میشد.ایادر efcf هست که میدونم نیست چطوری حل کرده.مخصوصا در ef
۲- من در efcf امدم جدوال دستی از بانک حذف کردم الان که تغغیران رو میدم میخام دوباره درست کنم این خطا رو میده
An error occurred while updating the entries. See the inner exception for details.
البته قبلا ش یه خطا دیگه میداد

The model backing the 'MyDBContext' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data

که با این دستور حلش کردم
 System.Data.Entity.Database.SetInitializer<Context>(null);
نظرات نظرسنجی‌ها
با توجه به آخرین نگارش‌های موجود Angular و React، انتخاب شما برای انجام یک پروژه بزرگ کدام است؟
یک نکته‌: در اینجا شما فرض‌تان بر این است که React یک فریم‌ورک است؛ به نظرم قرار دادن React در این بین مقایسه درستی نیست؛ چون React به خودی خود یک لایبرری است به این معنا که خیلی از concernهای (routing, data fetching, ...) ساخت یک اپلیکیشن را باید خودتان هندل کنید؛ پیاده‌سازی هرکدام از این موارد به شکل صحیح دشواری‌های خاص خود را دارد؛ بنابراین بهتر است به React به عنوان یک لایبرری و یا یک معماری نگاه کنید و برای ساخت اپلیکیشن‌ها از فریم‌ورک‌هایی که مبتنی بر آن توسعه داده شده‌اند (مانند Next.js, Remix, ...) استفاده کنید.

در مورد خود نظرسنجی هم به نظرم این انتخاب کاملاً به سایز تیم بستگی دارد؛ برای پروژه‌هایی که دات‌نت هستند پیشنهاد من Blazor است (مزایای آن نیز در سایت توضیح داده شده است) به خصوص برای اعضای تیمی که به عنوان فول‌استک هستند این امر خیلی مهم است؛ در اینحالت context switching با هزینه کمتری خواهید داشت و به اصطلاح developer experience بهتری نیز خواهید داشت.
When a developer switches context, they must first disengage from the task at hand and then shift their focus to the new task. This whole process takes time and can drain devs mentally. It takes a developer 25 minutes to refocus after a context switch. 

مطالب
تهیه XML امضاء شده جهت تولید مجوز استفاده از برنامه
اگر به فایل مجوز استفاده از برنامه‌‌ای مانند EF Profiler دقت کنید، یک فایل XML به ظاهر ساده بیشتر نیست:
<?xml version="1.0" encoding="utf-8"?>
<license id="17d46246-a6cb-4196-98a0-ff6fc08cb67f" expiration="2012-06-12T00:00:00.0000000" type="Trial" prof="EFProf">
  <name>MyName</name>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>b8N0bDE4gTakfdGKtzDflmmyyXI=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>IPELgc9BbkD8smXSe0sGqp5vS57CtZo9ME2ZfXSq/thVu...=</SignatureValue>
  </Signature>
</license>
در این فایل ساده متنی، نوع مجوز استفاده از برنامه، Trial ذکر شده است. شاید عنوان کنید که خوب ... نوع مجوز را به Standard تغییر می‌دهیم و فایل را ذخیره کرده و نهایتا استفاده می‌کنیم. اما ... نتیجه حاصل کار نخواهد کرد! حتی اگر یک نقطه به اطلاعات این فایل اضافه شود، دیگر قابل استفاده نخواهد بود. علت آن هم به قسمت Signature فایل XML فوق بر می‌گردد.
در ادامه به نحوه تولید و استفاده از یک چنین مجوزهای امضاء شده‌ای در برنامه‌های دات نتی خواهیم پرداخت.


تولید کلیدهای RSA

برای تهیه امضای دیجیتال یک فایل XML نیاز است از الگوریتم RSA استفاده شود.
برای تولید فایل XML امضاء شده، از کلید خصوصی استفاده خواهد شد. برای خواندن اطلاعات مجوز (فایل XML امضاء شده)، از کلیدهای عمومی که در برنامه قرار می‌گیرند کمک خواهیم گرفت (برای نمونه برنامه EF Prof این کلیدها را در قسمت Resourceهای خود قرار داده است).
استفاده کننده تنها زمانی می‌تواند مجوز معتبری را تولید کند که دسترسی به کلیدهای خصوصی تولید شده را داشته باشد.
        public static string CreateRSAKeyPair(int dwKeySize = 1024)
        {
            using (var provider = new RSACryptoServiceProvider(dwKeySize))
            {
                return provider.ToXmlString(includePrivateParameters: true);
            }
        }
امکان تولید کلیدهای اتفاقی مورد استفاده در الگوریتم RSA، در دات نت پیش بینی شده است. خروجی متد فوق یک فایل XML است که به همین نحو در صورت نیاز توسط متد provider.FromXmlString مورد استفاده قرار خواهد گرفت.


تهیه ساختار مجوز

در ادامه یک enum که بیانگر انواع مجوزهای برنامه ما است را مشاهده می‌کنید:
namespace SignedXmlSample
{
    public enum LicenseType
    {
        None,
        Trial,
        Standard,
        Personal
    }
}
به همراه کلاسی که اطلاعات مجوز تولیدی را دربر خواهد گرفت:
using System;
using System.Xml.Serialization;

namespace SignedXmlSample
{
    public class License
    {
        [XmlAttribute]
        public Guid Id { set; get; }
        
        public string Domain { set; get; }

        [XmlAttribute]
        public string IssuedTo { set; get; }

        [XmlAttribute]
        public DateTime Expiration { set; get; }

        [XmlAttribute]
        public LicenseType Type { set; get; }
    }
}
خواص این کلاس یا عناصر enum یاد شده کاملا دلخواه هستند و نقشی را در ادامه بحث نخواهند داشت؛ از این جهت که از مباحث XmlSerializer برای تبدیل وهله‌ای از شیء مجوز به معادل XML آن استفاده می‌شود. بنابراین المان‌های آن‌را مطابق نیاز خود می‌توانید تغییر دهید. همچنین ذکر ویژگی XmlAttribute نیز اختیاری است. در اینجا صرفا جهت شبیه سازی معادل مثالی که در ابتدای بحث مطرح شد، از آن استفاده شده است. این ویژگی راهنمایی است برای کلاس XmlSerializer تا خواص مزین شده با آن‌را به شکل یک Attribute در فایل نهایی ثبت کند.


تولید و خواندن مجوز دارای امضای دیجیتال

کدهای کامل کلاس تولید و خواندن یک مجوز دارای امضای دیجیتال را در اینجا مشاهده می‌کنید:
using System;
using System.IO;
using System.Security.Cryptography; // needs a ref. to `System.Security.dll` asm.
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace SignedXmlSample
{
    public static class LicenseGenerator
    {
        public static string CreateLicense(string licensePrivateKey, License licenseData)
        {
            using (var provider = new RSACryptoServiceProvider())
            {
                provider.FromXmlString(licensePrivateKey);
                var xmlDocument = createXmlDocument(licenseData);
                var xmlDigitalSignature = getXmlDigitalSignature(xmlDocument, provider);
                appendDigitalSignature(xmlDocument, xmlDigitalSignature);
                return xmlDocumentToString(xmlDocument);
            }
        }

        public static string CreateRSAKeyPair(int dwKeySize = 1024)
        {
            using (var provider = new RSACryptoServiceProvider(dwKeySize))
            {
                return provider.ToXmlString(includePrivateParameters: true);
            }
        }

        public static License ReadLicense(string licensePublicKey, string xmlFileContent)
        {
            var doc = new XmlDocument();
            doc.LoadXml(xmlFileContent);

            using (var provider = new RSACryptoServiceProvider())
            {
                provider.FromXmlString(licensePublicKey);

                var nsmgr = new XmlNamespaceManager(doc.NameTable);
                nsmgr.AddNamespace("sig", "http://www.w3.org/2000/09/xmldsig#");

                var xml = new SignedXml(doc);
                var signatureNode = (XmlElement)doc.SelectSingleNode("//sig:Signature", nsmgr);
                if (signatureNode == null)
                    throw new InvalidOperationException("This license file is not signed.");

                xml.LoadXml(signatureNode);
                if (!xml.CheckSignature(provider))
                    throw new InvalidOperationException("This license file is not valid.");

                var ourXml = xml.GetXml();
                if (ourXml.OwnerDocument == null || ourXml.OwnerDocument.DocumentElement == null)
                    throw new InvalidOperationException("This license file is coruppted.");

                using (var reader = new XmlNodeReader(ourXml.OwnerDocument.DocumentElement))
                {
                    var xmlSerializer = new XmlSerializer(typeof(License));
                    return (License)xmlSerializer.Deserialize(reader);
                }
            }
        }

        private static void appendDigitalSignature(XmlDocument xmlDocument, XmlNode xmlDigitalSignature)
        {
            xmlDocument.DocumentElement.AppendChild(xmlDocument.ImportNode(xmlDigitalSignature, true));
        }

        private static XmlDocument createXmlDocument(License licenseData)
        {
            var serializer = new XmlSerializer(licenseData.GetType());
            var sb = new StringBuilder();
            using (var writer = new StringWriter(sb))
            {
                var ns = new XmlSerializerNamespaces(); ns.Add("", "");
                serializer.Serialize(writer, licenseData, ns);
                var doc = new XmlDocument();
                doc.LoadXml(sb.ToString());
                return doc;
            }
        }

        private static XmlElement getXmlDigitalSignature(XmlDocument xmlDocument, AsymmetricAlgorithm key)
        {
            var xml = new SignedXml(xmlDocument) { SigningKey = key };
            var reference = new Reference { Uri = "" };
            reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
            xml.AddReference(reference);
            xml.ComputeSignature();
            return xml.GetXml();
        }

        private static string xmlDocumentToString(XmlDocument xmlDocument)
        {
            using (var ms = new MemoryStream())
            {
                var settings = new XmlWriterSettings { Indent = true, Encoding = Encoding.UTF8 };
                var xmlWriter = XmlWriter.Create(ms, settings);
                xmlDocument.Save(xmlWriter);
                ms.Position = 0;
                return new StreamReader(ms).ReadToEnd();
            }
        }
    }
}
توضیحات:
در حین کار با متد CreateLicense، پارامتر licensePrivateKey همان اطلاعاتی است که به کمک متد CreateRSAKeyPair قابل تولید است. توسط پارامتر licenseData، اطلاعات مجوز در حال تولید اخذ می‌شود. در این متد به کمک provider.FromXmlString، اطلاعات کلیدهای RSA دریافت خواهند شد. سپس توسط متد createXmlDocument، محتوای licenseData دریافتی به یک فایل XML نگاشت می‌گردد (بنابراین اهمیتی ندارد که حتما از ساختار کلاس مجوز یاد شده استفاده کنید). در ادامه متد getXmlDigitalSignature با در اختیار داشتن معادل XML شیء مجوز و کلیدهای لازم، امضای دیجیتال متناظری را تولید می‌کند. با استفاده از متد appendDigitalSignature، این امضاء را به فایل XML اولیه اضافه می‌کنیم. از این امضاء جهت بررسی اعتبار مجوز برنامه در متد ReadLicense استفاده خواهد شد.
برای خواندن یک فایل مجوز امضاء شده در برنامه خود می‌توان از متد ReadLicense استفاده کرد. توسط آرگومان licensePublicKey، اطلاعات کلید عمومی دریافت می‌شود. این کلید دربرنامه، ذخیره و توزیع می‌گردد. پارامتر xmlFileContent معادل محتوای فایل XML مجوزی است که قرار است مورد ارزیابی قرار گیرد.


مثالی در مورد نحوه استفاده از کلاس تولید مجوز

در ادامه نحوه استفاده از متدهای CreateLicense و  ReadLicense را ملاحظه می‌کنید؛ به همراه آشنایی با نمونه کلیدهایی که باید به همراه برنامه منتشر شوند:
using System;
using System.IO;

namespace SignedXmlSample
{
    class Program
    {
        static void Main(string[] args)
        {
            //Console.WriteLine(LicenseGenerator.CreateRSAKeyPair());
            writeLicense();            
            readLicense();

            Console.WriteLine("Press a key...");
            Console.ReadKey();
        }

        private static void readLicense()
        {
            var xml = File.ReadAllText("License.xml");
            const string publicKey = @"<RSAKeyValue>
                                    <Modulus>
                                        mBNKFIc/LkMfaXvLlB/+6EujPkx3vBOvLu8jdESDSQLisT8K96RaDMD1ORmdw2XNdMw/6ZBuJjLhoY13qCU9t7biuL3SIxr858oJ1RLM4PKhA/wVDcYnJXmAUuOyxP/vfvb798o6zAC1R2QWuzG+yJQR7bFmbKH0tXF/NOcSgbc=
                                    </Modulus>
                                    <Exponent>
                                        AQAB
                                    </Exponent>
                                 </RSAKeyValue>";

            var result = LicenseGenerator.ReadLicense(publicKey, xml);

            Console.WriteLine(result.Domain);
            Console.WriteLine(result.IssuedTo);
        }

        private static void writeLicense()
        {
            const string rsaData = @"<RSAKeyValue>
                    <Modulus>
                        mBNKFIc/LkMfaXvLlB/+6EujPkx3vBOvLu8jdESDSQLisT8K96RaDMD1ORmdw2XNdMw/6ZBuJjLhoY13qCU9t7biuL3SIxr858oJ1RLM4PKhA/wVDcYnJXmAUuOyxP/vfvb798o6zAC1R2QWuzG+yJQR7bFmbKH0tXF/NOcSgbc=
                    </Modulus>
                    <Exponent>
                        AQAB
                    </Exponent>
                    <P>
                        xwPKN77EcolMTD2O2Csv6k9Y4aen8UBVYjeQ4PtrNGz0Zx6I1MxLEFzRpiKC/Ney3xKg0Icwj0ebAQ04d5+HAQ==
                    </P>
                    <Q>
                        w568t0Xe6OBUfCyAuo7tTv4eLgczHntVLpjjcxdUksdVw7NJtlnOLApJVJ+U6/85Z7Ji+eVhuN91yn04pQkAtw==
                    </Q>
                    <DP>
                        svkEjRdA4WP5uoKNiHdmMshCvUQh8wKRBq/D2aAgq9fj/yxlj0FdrAxc+ZQFyk5MbPH6ry00jVWu3sY95s4PAQ==
                    </DP>
                    <DQ>
                        WcRsIUYk5oSbAGiDohiYeZlPTBvtr101V669IUFhhAGJL8cEWnOXksodoIGimzGBrD5GARrr3yRcL1GLPuCEvQ==
                    </DQ>
                    <InverseQ>
                        wIbuKBZSCioG6MHdT1jxlv6U1+Y3TX9sHED9PqGzWWpVGA+xFJmQUxoFf/SvHzwbBlXnG0DLqUvxEv+BkEid2w==
                    </InverseQ>
                    <D>                        Yk21yWdT1BfXqlw30NyN7qNWNuM/Uvh2eaRkCrhvFTckSucxs7st6qig2/RPIwwfr6yIc/bE/TRO3huQicTpC2W3aXsBI9822OOX4BdWCec2txXpSkbZW24moXu+OSHfAdYoOEN6ocR7tAGykIqENshRO7HvONJsOE5+1kF2GAE=
                    </D>
                  </RSAKeyValue>";

            string data = LicenseGenerator.CreateLicense(
                                                rsaData,
                                                new License
                                                {
                                                     Id = Guid.NewGuid(),
                                                     Domain = "dotnettips.info",
                                                     Expiration = DateTime.Now.AddYears(2),
                                                     IssuedTo = "VahidN",
                                                     Type = LicenseType.Standard
                                                });
            File.WriteAllText("License.xml", data);
        }
    }
}
ابتدا توسط متد CreateRSAKeyPair کلیدهای لازم را تهیه و ذخیره کنید. این کار یکبار باید صورت گیرد.
همانطور که مشاهده می‌کنید، اطلاعات کامل یک نمونه از آن، در متد writeLicense مورد نیاز است. اما در متد readLicense تنها به قسمت عمومی آن یعنی Modulus و Exponent نیاز خواهد بود (موارد قابل انتشار به همراه برنامه).

سؤال: امنیت این روش تا چه اندازه است؟
پاسخ: تا زمانیکه کاربر نهایی به کلیدهای خصوصی شما دسترسی پیدا نکند، امکان تولید معادل آن‌ها تقریبا در حد صفر است و به طول عمر او قد نخواهد داد!
اما ... مهاجم می‌تواند کلیدهای عمومی و خصوصی خودش را تولید کند. مجوز دلخواهی را بر این اساس تهیه کرده و سپس کلید عمومی جدید را در برنامه، بجای کلیدهای عمومی شما درج (patch) کند! بنابراین روش بررسی اینکه آیا برنامه جاری patch شده است یا خیر را فراموش نکنید. یا عموما مطابق معمول قسمتی از برنامه که در آن مقایسه‌ای بین اطلاعات دریافتی و اطلاعات مورد انتظار وجود دارد، وصله می‌شوند؛ این مورد عمومی است و منحصر به روش جاری نمی‌باشد.

دریافت نسخه جنریک این مثال:
SignedXmlSample.zip
اشتراک‌ها
به ویژوال استودیو 2022 خوش آمدید - توسط Scott Hanselman و دوستان

Want to learn about the latest and greatest in the 64-bit Visual Studio 2022? Join Scott Hanselman and Visual Studio product team as they take Visual Studio 2022 for a spin.


00:00 Intro 
00:39 Why you should care about Visual Studio 2022? 
02:20 Performance improvements in Visual Studio 2022 
04:39 Why 64-bit now? 
08:00 IntelliCode, type less code more 
11:35 Hot reload for C++ 
13:47 New for WPF and WinForms (Hot Reload, Design time data, XAML
17:20 Hot Reload in ASP.NET 

20:27 Profiling .NET apps in Visual Studio 2022 

23:19 Cross platform apps with WSL and CMake in Visual Studio 2022 

26:07 Testing your .NET app on Linux 

28:00 Easily create CI/CD pipelines using GitHub actions with Visual Studio  2022

30:40 Balloon drop! 

به ویژوال استودیو 2022 خوش آمدید - توسط Scott Hanselman و دوستان
اشتراک‌ها
پروژه ApiBoilerPlate برای ساخت پروژه های ASP.NET Core APIs

A simple yet organized project template for building ASP.NET Core APIs in .NET Core 3.1

Tools and Frameworks Used

  • .NET Core 3.1
  • ASP.NET Core - For building RESTful APIs
  • Dapper - For data access.
  • AutoMapper - For mapping entity models to DTOs.
  • AutoWrapper - For handling request Exceptions and consistent HTTP response format.
  • AutoWrapper.Server - For unwrapping the Result attribute from AutoWrapper's ApiResponse output.
  • Swashbuckle.AspNetCore - For securing API documentation.
  • FluentValidation.AspNetCore - For Model validations
  • Serilog.AspNetCore - For logging capabilities
  • IdentityServer4.AccessTokenValidation - For JWT Authentication handling
  • Microsoft.Extensions.Http.Polly - For handling HttpClient Resilience and Transient fault-handling
  • AspNetCoreRateLimit - For controlling the rate of requests that clients can make to an external API based on IP address or client ID.
  • AspNetCore.Diagnostics.HealthChecks - For performing health checks
  • Microsoft.AspNetCore.Diagnostics.HealthChecks - For getting the results of Health Checks in the application
  • AspNetCore.HealthChecks.UI - For Health Status visualization
  • xUnit and Moq - For unit testing.  


پروژه ApiBoilerPlate برای ساخت پروژه های ASP.NET Core APIs
اشتراک‌ها
مدل Actor با استفاده از Akka.net

In the same time when first object-oriented languages were emerging, another concept inspired by general relativity and quantum mechanics was taking shape – actor model. In general terms, the Actor model was defined 1973. and was developed on a platform of multiple independent processors in a network. Similar to the object-oriented approach, this essentially mathematical model, revolved around the concept of actors. An actor is the smallest structural unit of Actor model, and just like objects, they encapsulate data and behavior. In difference to objects, however, actors communicate with each other exclusively trough messages. Messages in actors are processed in a serial manner. According to the full definition of actors, they can do three things:

  • send a finite number of messages to other actors
  • create a finite number of new actors
  • designate the behavior to be used for the next message it receives 
مدل Actor با استفاده از Akka.net
اشتراک‌ها
انتشار SQL Server 2016 CTP 3.1

New In-Memory OLTP improvements in CTP3.1 include:

  • Unique indexes in memory-optimized tables, to complement the support for unique constraints that was released in CTP3
  • LOB data types varchar(max), nvarchar(max), and varbinary(max) in memory-optimized tables and natively compiled modules
  • Indexes with NULLable key columns in memory-optimized tables

Syntax inputdate AT TIME ZONE timezone.

  • Inputdate: An expression that can be resolved to a smalldatetime, datetime, datetime2, or datetimeoffset value.
  • Timezone: Name of the destination time zone in standard format as enumerated by Windows. Available time zones can be found by querying sys.time_zone_info.

SQL Server Analysis Services (SSAS) updates allow upgrading your existing models to 1200 compatibility level and a JSON editor for SSDT;

SQL Server PowerPivot and Reporting Services/Power View for SharePoint 2016 available now with CTP3.1!
انتشار SQL Server 2016 CTP 3.1
مطالب
ارتباط بین کامپوننت‌ها در Vue.js - قسمت سوم استفاده از تزریق وابستگی‌ها
در قسمت‌های قبلی( ^ و ^) نحوه‌ی ارتباط بین کامپوننت‌ها در Vue.js بررسی و مزایا و معایب آنها بیان شد. روش دیگری هم برای ارسال اطلاعات از کامپوننتِ Parent به فرزندانش وجود دارد که با استفاده از Dependency Injection یا به اختصار DI مقدور می‌باشد و در ورژن +2.2 معرفی شد که نحوه‌ی ارتباط بین کامپوننتِ Parent و فرزندانش را آسان نمود. پیش‌تر برای ارتباط از Parent به Child، از Props استفاده میکردیم، ولی اگر قرار بود در چند سطح این ارتباط عمیق باشد، باز هم مدیریت کردن Props مشکل و سخت بود. اکنون با استفاده از provide و inject قادر خواهیم بود تا آبجکت، فانکشن و یا دیتایِ یک کامپوننتِ Parent را در فرزندانش فراخوانی و استفاده کنیم. اگر در حالت عادی نیاز بود تا در دو سطح، یا بیشتر (مانند تصویر زیر) دیتایِ کامپوننت پدر را به فرزند، نوه و ... انتقال دهیم، می‌بایست اطلاعات را بصورت Props به هر Level انتقال دهیم.



روش جاری شباهت زیادی به استفاده از Context در React دارد:

Context provides a way to pass data through the component tree without having to pass props down manually at every level


جهت به اشتراک گذاری دیتا یا تابعی در کامپوننت Parent با Children، به شکل زیر عمل میکنیم. در اینجا با استفاده از provide، دیتای foo به اشتراک گذاشته شده‌است:
// parent component providing 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}
و در کامپوننت‌های فرزند به شکل زیر میتوانیم مقدار foo را دریافت کنیم:
// child component injecting 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

میتوانیم مقدار پیش فرض دیتایِ ارسالی از کامپوننت Parent را در قسمت data و props در کامپوننت Child دریافت نماییم:
Using an injected value as the default for a prop
//دریافت میکنیم props در قسمت  child را در کامپوننت  foo مقدار
const Child = {
  inject: ['foo'],
  props: {
    bar: {
      default () {
        return this.foo
      }
    }
  }
}

Using an injected value as data entry
//دریافت میکنیم data در قسمت  child را در کامپوننت  foo مقدار
const Child = {
  inject: ['foo'],
  data () {
    return {
      bar: this.foo
    }
  }
}

نکته: در این روش در صورتیکه دیتایِ به اشتراک گذاشته شده در کامپوننتِ Parent تغییر کند، مقدار آن در کامپوننت Child تغییری نخواهد کرد و مانند روش‌های قبلی (^ و ^) نیست و نیاز به نوشتن کدی برای تعامل داشتن و به‌روز رسانی مقادیر، در کامپوننت Child می‌باشد.
کد زیر  را در نظر بگیرید؛ با زدن دکمه‌ی Increment counter  مقدار counter در کامپوننتِParent تغییر میکند، ولی در کامپوننت Child، مقدار counter_in_child  تغییری حاصل نمی‌کند.
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <title>Dependency injection</title>
</head>

<body>
  <div id="app">
    <button @click="counter++">Increment counter</button>
    <h2>Parent</h2>
    <p>{{counter}}</p>
    <div>
      <h3>Child</h3>
      <child></child>
    </div>
  </div>
  
<script>
const Child = {
  inject: ['counter_in_child'],
  template: `<div>Counter Child is:{{ counter_in_child }}</div>`
};

new Vue ({
  el: "#app",
  components: { Child },
  provide() {
    return {
      counter_in_child: this.counter
    };
  },
  data() {
    return {
      counter: 0
    };
  }
});
</script>

</body>
</html>
       
برای اینکه بتوان تغییرات ایجاد شده‌ی بر روی دیتا را در کامپوننتِChild، مشاهده کرد، نیاز داریم کد زیر را در قسمت provide به ازای آن دیتا اضافه کنیم: 
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <title>Dependency injection</title>
</head>

<body>
  <div id="app">
    <button @click="counter++">Increment counter</button>
    <h2>Parent</h2>
    <p>{{counter}}</p>
    <div>
      <h3>Child</h3>
      <child></child>
    </div>
  </div>
  
<script>
const Child = {
  inject: ['counter_in_child'],
  template: `<div>Counter Child is:{{ counter_in_child.counter }}</div>`
};

new Vue ({
  el: "#app",
  components: { Child },
  provide() {
    const counter_in_child={};
Object.defineProperty(counter_in_child,'counter',{
enumerable:true,
get:()=>this.counter
})
    return {
      counter_in_child
    };
  },
  data() {
    return {
      counter: 0
    };
  }
});
</script>

</body>
</html>

مثالی از نحوه به اشتراک گذاری متد بین Parent و Child.

نتیجه گیری:
A) استفاده از این روش مرسوم نیست و بیشتر برای ساخت پلاگین در Vuejs مورد استفاده قرار میگیرد:
provide  and  inject  are primarily provided for advanced plugin / component library use cases. It is NOT recommended to use them in generic application code
B) برای استفاده از این روش کتابخانه‌هایی جهت ساده‌تر کردن بکارگیری ایجاد شده‌است.
C) این روش برای ارتباط  Sibling Component مناسب نیست.
مطالب
قابلیت چند زبانه و Localization در AngularJs- بخش چهارم و نهایی: Best Practiceهای angular-translate
در بخش پیشین چند مورد از قابلیت‌های angular-translate را بررسی نمودیم. در این بخش به بررسی باقی موارد می‌پردازیم.

ex7_load_static_files 

در این مثال خواهیم دید که چگونه یک فایل translate table در موقع فراخوانی به صورت On Demand بارگذاری خواهد شد. در قدم اول اسکریپت‌های زیر به صفحه افزوده می‌شوند.
    <script src="Scripts/angular.js"></script>
    <script src="Scripts/angular-cookies.js"></script>
    <script src="Scripts/angular-translate.js"></script>
    <script src="Scripts/angular-translate-storage-cookie.js"></script>
    
    <!-- for override loader methods in angular translate -->
    <script src="/src/service/loader-static-files.js"></script>
در ادامه درباره‌ی اسکریپت پنجم بیشتر توضیح خواهیم داد. بگذارید از آخر به اول شروع کنیم و ببینیم که نحوه‌ی فراخوانی و استفاده از امکان on demand بارگذاری شدن فایل‌های زبان به چه صورتی می‌باشد. در زیر، تکه کد اصافه شده به ex7 را مشاهده می‌کنید:
            // Register a loader for the static files
            // So, the module will search missing translation tables under the specified urls.
            // Those urls are [prefix][langKey][suffix].
            $translateProvider.useStaticFilesLoader({
                prefix: '/l10n/',
                suffix: '.json'
            });
همانطور که در توضیحات آمده است، ماژول با دریافت prefix و suffix که در حقیقت همان فولدر و پسوند فایل‌های translate table هستند، هر زبانی را که مورد نیاز است و تا کنون بارگذاری نشده، بارگذاری می‌نماید. تصویر زیر محتویات فولدر l10n را نمایش می‌دهد.

حال ببینیم که این فرآیند در loader-static-files چگونه پیاده سازی شده است. در این فایل یک متد load نوشته شده است که فایل‌های static را طبق یک الگوی مشتمل بر prefix و suffix از سرور می‌خواند. لزومی ندارد که شما فایل‌ها را حتما به صورت JSON و با این پسوند ذخیره کنید. اما چیزی که قطعی است این است که فایل‌ها حتما باید به صورت key value ذخیره شده باشند.

تکه کد زیر اطلاعات فایل loader-static-files را نمایش می‌دهد.

angular.module('pascalprecht.translate')
.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);
function $translateStaticFilesLoader($q, $http) {
    
  'use strict';

  return function (options) {

    if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {
      throw new Error('Couldn\'t load static files, no files and prefix or suffix specified!');
    }

    if (!options.files) {
      options.files = [{
        prefix: options.prefix,
        suffix: options.suffix
      }];
    }

    var load = function (file) {
      if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {
        throw new Error('Couldn\'t load static file, no prefix or suffix specified!');
      }

      var deferred = $q.defer();

      $http(angular.extend({
        url: [
          file.prefix,
          options.key,
          file.suffix
        ].join(''),
        method: 'GET',
        params: ''
      }, options.$http)).success(function (data) {
        deferred.resolve(data);
      }).error(function () {
        deferred.reject(options.key);
      });

      return deferred.promise;
    };

    var deferred = $q.defer(),
        promises = [],
        length = options.files.length;

    for (var i = 0; i < length; i++) {
      promises.push(load({
        prefix: options.files[i].prefix,
        key: options.key,
        suffix: options.files[i].suffix
      }));
    }

    $q.all(promises).then(function (data) {
      var length = data.length,
          mergedData = {};

      for (var i = 0; i < length; i++) {
        for (var key in data[i]) {
          mergedData[key] = data[i][key];
        }
      }

      deferred.resolve(mergedData);
    }, function (data) {
      deferred.reject(data);
    });

    return deferred.promise;
  };
}

$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';

همانطور که ملاحظه می‌کنید، کد فوق یک سرویس با نام $translateStaticFilesLoader را تعریف نموده است. در صورتیکه ما در کنترلر فایل ex7، اصلا نامی از آن نبردیم و تنها از $translateProvider.useStaticFilesLoader استفاده نمودیم! جواب در نحوه‌ی نگارش کد angular-translate نهفته است. در خط 866 فایل angular-translate تکه کد زیر مربوط به تعریف translateStaticFileLoader می‌باشد. همانطور که ملاحظه می‌کنید سرویس translateStaticFilesLoader درون فضای نام سرویس translateTable قرار گرفته است. بنابراین ما تنها با تعریف سرویس translateStaticFilesLoader، در حقیقت آن را override نموده‌ایم. در کد نمونه‌ای که در بخش‌های قبلی قرار داده‌ام یک فایل translate.js نیز قرار دارد که در فولدر src/services قرار گرفته است. این فایل نیز برخی از امکانات و سرویس‌های built-in درون angular-translate را سفارشی نموده است.

  /**
   * @ngdoc function
   * @name pascalprecht.translate.$translateProvider#useStaticFilesLoader
   * @methodOf pascalprecht.translate.$translateProvider
   *
   * @description
   * Tells angular-translate to use `$translateStaticFilesLoader` extension service as loader.
   *
   * @param {Object=} options Optional configuration object
   */
  this.useStaticFilesLoader = function (options) {
    return this.useLoader('$translateStaticFilesLoader', options);
  };

در این 4 مجموعه سعی کردم تمامی آنچه را که برای ایجاد قابلیت چند زبانه و localization نیاز است و حیاتی بود، تشریح کنم. بنابراین تا کنون دانش خوبی درباره‌ی این کتابخانه کسب نموده‌اید. باقی تمرین‌ها را می‌توانید بر حسب نیاز با استفاده از مستندات موجود در angular-translate مطالعه و استفاده نمایید.

اشتراک‌ها
نگاهی دیگر به آمار بررسی وضعیت جاوا اسکریپت در سال 2017

Insight #1: React is here to stay
Insight #2: Angular is shifting to a new role --> enterprise apps
Insight #3: You can’t ignore Vue.js anymore
Insight #4: Knowledge of some libraries will help you earn more (but not for the reasons you might think)
Insight #5: 2018 will be the year of GraphQL
Insight #6: JavaScript != Front-end
Insight #7: Microsoft is striking back
Insight #8: JavaScript is different around the world
Insight #9: Typed JavaScript is on the rise
Insight #10: JavaScript is whatever you want it to be

نگاهی دیگر به آمار بررسی وضعیت جاوا اسکریپت در سال 2017