چگونه از کد خود محافظت کنیم؟
Soft Delete در Entity Framework 6
ضمنا این ویرایشگر با نگارشهای نهایی مرورگرها سازگاری خوبی دارد.
تصمیم گرفتم در طی چندین پست در حد توانم به آموزش jQuery بپردازم. (مطالب نوشته شده برداشت ازادی از کتاب jQuery in action است)
جی کوئری (jQuery) چیست؟
نکته: برای استفاده از جی کوئری باید HTML و CSS و جاوا اسکریپت آشنایی داشته باشید.
چگونه از جی کوئری استفاده کنیم؟
برای استفاده از جی کوئری باید ابتدا فایل آن را از سایت آن دانلود کرده و در پروژه خود استفاده نمایید. البته روشهای دیگری برای استفاده از این فایل وجود دارد که در آینده بیشتر با آن آشنا خواهیم شد. برای استفاده از این فایل در پروژه باید به شکل زیر آن را به صفحه HTML خود معرفی کنیم.
<html> <head> <script type="text/javascript" src="jquery-1.9.1.min.js"></script> </head> <body> </body> </html>
کوتاه کردن کد: هر زمان شما خواسته باشید کارکرد یک صفحه وب را پویاتر کنید، در اکثر مواقع به ناچار این کار از طریق عناصری بروی صفحه انجام داده اید که با توجه به انتخاب شدن آنها، صفحه کارکردی خاص خواهد داشت. مثلا در جاوا اسکریپت اگر بخواهیم عنصری را که در یک radioGroup انتخاب شده است را برگردانیم باید کدهای زیر را بنویسیم:
var checkedValue; var elements = document.getElementByTagName ('input'); for (var n = 0; n < elements.length; n++) { if (elements[n].type == 'radio' && elements[n].name == 'myRadioGroup' && elements[n].checked) { checkedValue = elements[n].value; } }
var checkedValue = $ ('[name="myRadioGroup"]:checked').val();
قدرت اصلی جی کوئری برگفته از انتخابکنندهها (Selector) هاست، انتخابکننده ، یک عبارت است که دسترسی به عنصری خاص بر روی صفحه را موجب میشود؛ انتخابکننده این امکان را فراهم میسازد تا به سادگی عنصر مورد نظر را مشخص و به آن دسترسی پیدا کنیم که در مثال فوق، عنصر مورد نظر ما گزینه انتخاب شده از myRadioGroup بود.
Unobtrusive JavaScript: اگر پیش از پیدایش CSS در کار ایجاد صفحههای اینترنتی بودهاید حتما مشکلات و مشقات آن دوران را به خاطر میآورید. در آن زمان برای فرمتدهی به اجزای مختلف صفحه ، به ناچار علائم فرمتدهی را به همراه دستورات خود اجزا، در صفحههای HTML استفاده میکردیم. اکنون بسیار بعید به نظر میرسد کسی ترجیح دهد فرمتدهی اجزا را به همراه دستورهای HTML آن انجام دهد. اگر چه هنوز دستوری مانند زیر بسیار عادی به نظر میآید:
<button type="button" onclick="document.getElementById('xyz').style.color='red';"> Click Me </button>
مجموعه عناصر در جی کوئری:
زمانی که CSS به عنوان یک تکنولوژی به منظور جداسازی طراحی از ساختار به دنیای صفحههای اینترنتی معرفی شد، میبایست راهی برای اشاره به اجزای صفحات از طرف فایل CSS نیز معرفی میشد. این امر از طریق انتخابکنندهها (Selector) صورت پذیرفت.
برای مثال انتخابکننده زیر، به تمام عناصر <a> اشاره دارد که در یک عنصر <p> قرار گرفتهاند:
p a
برای انتخاب مجموعهای از عناصر از یکی از دو Syntax زیر استفاده میکنیم.
$(Selector) یا jQuery(Selector)
مثال زیر نمونهای دیگر است که در آن مجموعهای از تمام لینکهایی که درون تگ <p> قرار دارند را انتخاب میکند:
$("p a")
در اصطلاح برنامه نویسی به چنین توابعی که گروهی از عناصر را جمع میکنند، Wrapper میگویند زیرا تمام عناصر مطلوب را تحت یک شی بستهبندی میکند. در جیکوئری به آنها Wrapped Set یا jQuery Wrapper میگویند و به متدهایی که قابل اعمال بروی اینها به نام jQuery Wrapper Methodes شناخته میشوند.
در مثال زیر میخواهیم تمام عناصر <div> در صورتی که دارای کلاس notLongForThisWorldباشند را مخفی (با فید شدن) کنیم.
$("div.notLongForThisWorld").fadeOut();
فرض کنید در مثال بالا بخواهیم پس از مخفی کردن هر <div> بخواهیم یک کلاس به نام removedبه آن بیافزاییم. به این منظور میتوان کدی مانند زیر نوشت:
$("div.notLongForThisWorld").fadeOut().addClass("removed");
چند نمونه انتخاب کننده:
نتیجه | انتخاب کننده | |
تمام <p>های زوج را انتخاب میکند | $('p:even') | |
سطر اول هر جدول را انتخاب میکند | $("tr:nth-child(1)"); | |
<div>هایی که مستقیما در <body> تعریف شده باشند را انتخاب میکند. | $("body > div"); | |
لینک هایی که به یک فایل pdf اشاره دارند را انتخاب میکند. | $("a[href$=pdf]"); | |
تمام <div> هایی که مستقیما در <body> معرفی شده اند و دارای لینک میباشند را انتخاب میکند. | $("body > div:has(a)") | |
ادامه مطالب در پستهای بعدی تشریح خواهد شد.
جهت مطالعه بیشتر میتوانید از این منابع ^ و ^ و ^ و ^ و ^ استفاده کنید.
موفق و موید باشید
gRPC در دات نت ۵
برای انتقال دادهها از طریق WCF بین سیستمهای مختلف باید دادههای مورد نظر حتما سریالایز شوند که مثال هایی از این دست رو در همین سایت میتونید مطالعه کنید:
(^ ) و (^ ) و (^ )
با توجه به این که دادهها سریالایز میشوند، در نتیجه امکان انقال داده هایی که از نوع object هستند در WCF وجود ندارد. بلکه نوع داده باید صراحتا ذکر شود و این نوع باید قابیلت سریالایز شدن را دارا باشد.برای مثال شما نمیتونید متدی داشته باشید که پارامتر ورودی آن از نوع delegate باشد یا کلاسی باشد که صفت [Serializable] در بالای اون قرار نداشته باشد یا کلاسی باشد که صفت DataContract برای خود کلاس و صفت DataMember برای خاصیتهای اون تعریف نشده باشد. حالا سوال مهم این است اگر متدی داشته باشیم که پارامتر ورودی آن حتما باید از نوع delegate باشد چه باید کرد؟
برای تشریح بهتر مسئله یک مثال میزنم؟
سرویسی داریم برای اطلاعات کتاب ها. قصد داریم متدی بنوسیم که پارامتر
ورودی آن از نوع Lambda Expression است تا Query مورد نظر کاربر از سمت
کلاینت به سمت سرور دریافت کند و خروجی مورد نظر را با توجه به Query ورودی
به کلاینت برگشت دهد.( متدی متداول در اکثر پروژه ها). به صورت زیر عمل میکنیم.
*ابتدا یک Blank Solution ایجاد کنید.
*یک ClassLibrary به نام Model ایجاد کنید و کلاسی به نام Book در آن بسازید .(همانطور که میبینید کلاس مورد نظر سریالایز شده است):
[DataContract] public class Book { [DataMember] public int Code { get; set; } [DataMember] public string Title { get; set; } }
یک Contract برای ارتباط بین سرور و کلاینت میسازیم:
using System; using System.Collections.Generic; using System.Linq.Expressions; using System.ServiceModel; namespace WcfLambdaExpression { [ServiceContract] public interface IBookService { [OperationContract] IEnumerable<Book> GetByExpression( Expression<Func<Book, bool>> expression ); } }
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace WcfLambdaExpression { public class BookService : IBookService { public BookService() { ListOfBook = new List<Book>(); } public List<Book> ListOfBook { get; private set; } public IEnumerable<Book> GetByExpression( Expression<Func<Book, bool>> expression ) { ListOfBook.AddRange( new Book[] { new Book(){Code = 1 , Title = "Book1"}, new Book(){Code = 2 , Title = "Book2"}, new Book(){Code = 3 , Title = "Book3"}, new Book(){Code = 4 , Title = "Book4"}, new Book(){Code = 5 , Title = "Book5"}, } ); return ListOfBook.AsQueryable().Where( expression ); } } }
به طور حتم با خطا روبرو خواهید شد. دلیل آن هم این است که امکان سریالایز کردن برای پارامتر ورودی expression میسر نیست.
خطای مربوطه به شکل زیر خواهد بود:
Type 'System.Linq.Expressions.Expression`1[System.Func`2[WcfLambdaExpression.Book,System.Boolean]]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types
روشهای زیادی برای بر طرف کردن این محدودیت وجود دارد. اما در این پست روشی رو که خودم از اون استفاده میکنم رو براتون شرح میدهم.
در این روش باید از XElement استفاده شود که در فضای نام System.Linq.Xml قرار دارد. یعنی آرگومان ورودی سمت کلاینت باید به فرمت Xml سریالایز شود و سمت سرور دوباره دی سریالایز شده و تبدیل به یک Lambda Expression شود. اما سریالایز کردن Lambda Expression واقعا کاری سخت و طاقت فرساست . با توجه به این که در اکثر پروژهها این متدها به صورت Generic نوشته میشوند. برای حل این مسئله بعد از مدتی جستجو، کلاسی رو پیدا کردم که این کار رو برام انجام میداد. بعد از مطالعه دقیق و مشاهده روش کار کلاس، تغییرات مورد نظرم رو اعمال کردم و الان در اکثر پروژه هام دارم از این کلاس استفاده میکنم.
یک مثال از روش استفاده :
برای اینکه از این کلاس در هر دو پروژه (سرور و کلاینت) استفاده میکنیم باید یک Class Library جدید به نام Common بسازید و یک ارجاع از اون رو به هر دو پروژه سمت سرور و کلاینت بدید.
سرویس و Contract بالا رو به صورت زیر باز نویسی کنید.
[ServiceContract] public interface IBookService { [OperationContract] IEnumerable<Book> GetByExpression( XElement expression ); }
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Xml.Linq; namespace WcfLambdaExpression { public class BookService : IBookService { public BookService() { ListOfBook = new List<Book>(); } public List<Book> ListOfBook { get; private set; } public IEnumerable<Book> GetByExpression( XElement expression ) { ListOfBook.AddRange( new Book[] { new Book(){Code = 1 , Title = "Book1"}, new Book(){Code = 2 , Title = "Book2"}, new Book(){Code = 3 , Title = "Book3"}, new Book(){Code = 4 , Title = "Book4"}, new Book(){Code = 5 , Title = "Book5"}, } ); Common.ExpressionSerializer serializer = new Common.ExpressionSerializer(); return ListOfBook.AsQueryable().Where( serializer.Deserialize( expression ) as Expression<Func<Book, bool>> ); } }
using System; using System.Linq.Expressions; using TestExpression.MyBookService; namespace TestExpression { class Program { static void Main( string[] args ) { BookServiceClient bookService = new BookServiceClient(); Expression<Func<Book, bool>> expression = x => x.Code > 2 && x.Code < 5; Common.ExpressionSerializer serializer = new Common.ExpressionSerializer(); bookService.GetByExpression( serializer.Serialize( expression ) ); } } }
خروجی هم به صورت زیر خواهد بود:
دریافت سورس کامل Expression-Serialization