<input dir="ltr" class="form-control input-validation-error" type="email" data-val="true" data-val-email="'آدرس ایمیل' is not a valid email address." data-val-remote="این آدرس ایمیل هم اکنون مورد استفادهاست" data-val-remote-url="/Home/ValidateUniqueEmail" data-val-required="'آدرس ایمیل' must not be empty." id="Email" name="Email" >
افزودن آدرس ایمیل به مدل کاربران
به همان مدل قسمت قبل، قصد داریم خاصیت آدرس ایمیل را هم اضافه کنیم:
using System.ComponentModel.DataAnnotations; namespace FluentValidationSample.Models { public class UserModel { [Display(Name = "نام کاربری")] public string Username { get; set; } [Display(Name = "سن")] public int Age { get; set; } [Display(Name = "سابقه کار")] public int Experience { get; set; } [DataType(DataType.EmailAddress)] [Display(Name = "آدرس ایمیل")] public string Email { get; set; } } }
ایجاد سرویسی برای بررسی منحصربفرد بودن آدرس ایمیل
در ادامه قصد داریم سرویسی را ایجاد کنیم که برای مثال با بانک اطلاعاتی ارتباط برقرار کرده (در اینجا جهت سهولت ارائه، از یک آرایه استفاده شدهاست) و مشخص میکند که آیا ایمیل دریافتی پیشتر استفاده شدهاست یا خیر:
using System.Linq; namespace FluentValidationSample.Services { public interface IUsersService { bool IsUniqueEmail(string emailAddress); } public class UsersService : IUsersService { public bool IsUniqueEmail(string emailAddress) { string[] registedEmails = { "email@site.com", "test@gmail.com" }; return !registedEmails.Contains(emailAddress); } } }
namespace FluentValidationSample.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddScoped<IUsersService, UsersService>();
ایجاد اعتبارسنج سمت سرور بررسی منحصربفرد بودن آدرس ایمیل
در ادامه یک PropertyValidator جدید را ایجاد میکنیم تا بتوان توسط آن مقدار ایمیل دریافتی را در سمت سرور، تعیین اعتبار کرد:
using FluentValidation.Validators; using FluentValidationSample.Services; namespace FluentValidationSample.ModelsValidations { public class UniqueEmailValidator : PropertyValidator { private readonly IUsersService _usersService; public UniqueEmailValidator(IUsersService usersService) : base("این آدرس ایمیل هم اکنون مورد استفادهاست") { _usersService = usersService; } protected override bool IsValid(PropertyValidatorContext context) { return context.PropertyValue != null && _usersService.IsUniqueEmail((string)context.PropertyValue); } } }
پس از آن جهت سهولت استفادهی از آن، یک متد الحاقی جدید را نیز به نام UniqueEmail به نحو زیر تعریف میکنیم:
using FluentValidation; using FluentValidationSample.Services; namespace FluentValidationSample.ModelsValidations { public static class CustomValidatorExtensions { public static IRuleBuilderOptions<T, string> UniqueEmail<T>( this IRuleBuilder<T, string> ruleBuilder, IUsersService usersService) { return ruleBuilder.SetValidator(new UniqueEmailValidator(usersService)); } } }
یک نکته: اگر دقت کرده باشید، فضای نام این اعتبارسنج در این قسمت FluentValidationSample.ModelsValidations شدهاست:
علت اینجا است که اعتبارسنج تعریف شده نیاز دارد هم از مدلها استفاده کند و هم از سرویس کاربران. سرویس کاربران هم از مدلها استفاده میکند. به همین جهت اگر تعاریف اعتبارسنجی را داخل پروژهی مدلها قرار دهیم، یک وابستگی حلقوی رخ خواهد داد (وابستگی مدلها به سرویسها و برعکس). بنابراین بهتر است اعتبارسنجها را به یک پروژهی مجزا منتقل کنیم تا از بروز این cyclic dependency جلوگیری شود.
اعمال اعتبارسنجی منحصربفرد بودن ایمیل دریافتی به اعتبارسنج UserModel
پس از تهیهی متد الحاقی UniqueEmail، آنرا به RuleFor مخصوص خاصیت ایمیل اضافه میکنیم. در اینجا نیز تزریق وابستگی سرویس سفارشی IUsersService به سازندهی کلاس اعتبارسنج مجاز است:
using FluentValidation; using FluentValidationSample.Models; using FluentValidationSample.Services; namespace FluentValidationSample.ModelsValidations { public class UserModelValidator : AbstractValidator<UserModel> { public UserModelValidator(IUsersService usersService) { RuleFor(x => x.Username).NotNull(); RuleFor(x => x.Age).NotNull(); RuleFor(x => x.Experience).LowerThan(nameof(UserModel.Age)).NotNull(); RuleFor(x => x.Email).EmailAddress().NotNull().UniqueEmail(usersService); } } }
ایجاد متادیتای مورد نیاز جهت unobtrusive java script validation در سمت سرور
در ادامه نیاز است ویژگیهای data-val خاص unobtrusive java script validation را توسط FluentValidation ایجاد کنیم:
using FluentValidation; using FluentValidation.AspNetCore; using FluentValidation.Internal; using FluentValidation.Resources; using FluentValidation.Validators; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; namespace FluentValidationSample.ModelsValidations { public class RemoteClientValidator : ClientValidatorBase { public string RemoteUrl { set; get; } public RemoteClientValidator(PropertyRule rule, IPropertyValidator validator) : base(rule, validator) { } public override void AddValidation(ClientModelValidationContext context) { MergeAttribute(context.Attributes, "data-val", "true"); MergeAttribute(context.Attributes, "data-val-remote", GetErrorMessage(context)); MergeAttribute(context.Attributes, "data-val-remote-url", RemoteUrl); } private string GetErrorMessage(ClientModelValidationContext context) { var formatter = ValidatorOptions.MessageFormatterFactory().AppendPropertyName(Rule.GetDisplayName()); string messageTemplate; try { messageTemplate = Validator.Options.ErrorMessageSource.GetString(null); } catch (FluentValidationMessageFormatException) { messageTemplate = ValidatorOptions.LanguageManager.GetStringForValidator<NotEmptyValidator>(); } return formatter.BuildMessage(messageTemplate); } } }
<input dir="ltr" class="form-control input-validation-error" type="email" data-val="true" data-val-email="'آدرس ایمیل' is not a valid email address." data-val-remote="این آدرس ایمیل هم اکنون مورد استفادهاست" data-val-remote-url="/Home/ValidateUniqueEmail" data-val-required="'آدرس ایمیل' must not be empty." id="Email" name="Email" >
افزودن اعتبارسنجهای تعریف شده به تنظیمات برنامه
پس از تعریف UniqueEmailValidator و RemoteClientValidator، روش افزودن آنها به تنظیمات FluentValidation به صورت زیر است:
namespace FluentValidationSample.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddScoped<IUsersService, UsersService>(); services.AddControllersWithViews().AddFluentValidation( fv => { fv.RegisterValidatorsFromAssembly(Assembly.GetExecutingAssembly()); fv.RegisterValidatorsFromAssemblyContaining<RegisterModelValidator>(); fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false; fv.ConfigureClientsideValidation(clientSideValidation => { // ... clientSideValidation.Add( validatorType: typeof(UniqueEmailValidator), factory: (context, rule, validator) => new RemoteClientValidator(rule, validator) { RemoteUrl = "/Home/ValidateUniqueEmail" }); }); } ); }
namespace FluentValidationSample.Web.Controllers { public class HomeController : Controller { private readonly IUsersService _usersService; public HomeController(IUsersService usersService) { _usersService = usersService; } // ... public IActionResult ValidateUniqueEmail(string email) { return Ok(_usersService.IsUniqueEmail(email)); } } }
تعریف کدهای جاوا اسکریپتی مورد نیاز
پیش از هرکاری، اسکریپتهای فایل layout برنامه باید چنین تعریفی را داشته باشند:
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script> <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script> <script src="~/js/site.js" asp-append-version="true"></script>
آزمایش برنامه
View این قسمت نیز همانند قسمت قبل است که فقط یک آدرس ایمیل به آن اضافه شدهاست:
برای آزمایش آن اگر برای مثال یکی از آدرسهای ایمیل از پیش تعریف شدهی در متد IsUniqueEmail سرویس کاربران را وارد کنیم، با خطای اعتبارسنجی سمت کلاینت فوق روبرو خواهیم شد.
کدهای کامل این سری را تا این قسمت از اینجا میتوانید دریافت کنید: FluentValidationSample-part04.zip
چرا برنامه نویسی موبایل؟
با افزایش روزافزون SmartPhone ها و تبلتها، بازار تکنولوژی به این سمت سوق پیدا کردهاست. از این رو شرکتهای ارائه دهنده نرم افزاری، از این موقعیت استفاده کرده و هر کدام پلتفرم متفاوتی را برای برنامه نویسی بر روی این اسمارت فونها ارائه دادهاند. یکی از بزرگترین دغدغههای امروزه شرکتهای برنامه نویسی و توسعه نرم افزار موبایل، انتخاب درست پلتفرم برای توسعه نرم افزار میباشد. در این مقاله قصد دارم یکی از این پلت فرمها را بررسی کرده و معرفی کنم.
شرکت xamarin کار خود را در سال 2011 با ارایه نسخه Cross Platform پلتفرم .Net به نام Mono آغاز کرد. بعد از ارایه این نسخه از .Net، زامارین به کمک Mono توانست پیاده سازی بر روی Android و IOS را به نامهای MonoForAndroid و MonoTouch ارایه دهد. بعد از این نسخهها برنامه نویسان توانستند بر روی سیستم عاملهای اندروید و آی او اس به صورت Native کد خود را به زبان C# نوشته و آنها را اجرا کنند.
چرا باید از Xamarin استفاده کنم؟
در ادامه مقاله قصد دارم شما را با برخی از ویژگیهای زامارین آشنا کرده و مزایای استفاده از آن را بیان کنم.
Xamarin امکانی را فراهم کردهاست که برنامه نویسان به دو روش متفاوت قادر خواهند بود برنامههای خود را بنویسند:
Xamarin Native :1
زامارین به شما این امکان را میدهد که بتوانید به صورت مستقیم برای هر پلتفرم به صورت جداگانه برنامه نویسی کنید. در اندروید اینکار با Xamarin.Droid و در IOS اینکار با Xamarin.Touch امکانپذیر است. مزیتهای استفاده از این روش عبارتند از:
· بهره گیری از یک زبان برنامه نویسی
همانطور که میدانید یادگیری یک زبان برنامه نویسی هزینهی زیادی را برای یک سازمان و یا یک شخص به همراه دارد. در زامارین این امکان فراهم شدهاست که با استفاده از تنها یک زبان برنامه نویسی مانند C# ، برنامه نویسان بتوانند برای پلتفرمهای مختلف برنامه بنویسند. در نظر داشته باشید که UI در هر پلتفرم به صورت جداگانه پیاده سازی میشود. به طور مثال در اندروید به وسیلهی Android Xml میتوانید ظاهر برنامه خود را پیاده سازی کنید و منطقهای خود را با زبان C# برای تمامی پلت فرمها به صورت یکسان بنویسید.
· تجربه کاربری Native
زامارین به شما این امکان را خواهد داد که با استفاده از کنترلهای Native هر پلتفرم به تجربه کاربری همان پلت فرم دسترسی پیدا کنید و اپلیکیشنی با ظاهر و UX همان پلتفرم بسازید.
· استفاده 100% از امکانات هر پلتفرم
زامارین به دلیل Native بودن این امکان را به برنامه نویسان ارائه میدهد که با استفاده از یک زبان و با بکارگیری Cycle Life مخصوص هر پلتفرم، به 100% امکانات و API های هر پلتفرم دسترسی پیدا کنند.
· Performance
به دلیل اینکه برنامههای زامارین به صورت Native اجرا میشوند Performance بالایی دارند.
· دسترسی به API های موجود در .Net
شما قادر خواهید بود با دانش موجود مانند Entity Framework Code و.. به فریم ورک .Net دسترسی پیدا کرده و از API های درون آن استفاده کنید. زامارین از یکی از پیاده سازیهای .Net Standard استفاده میکند.
· استفاده مجدد از کد
در زامارین قادر خواهید بود که از کدهای خود، استفاده مجدد کرده و این امر سبب مدیریت بهتر بر روی کد، کد نویسی کمتر، هزینه نگهداری کد کمتر، توسعه راحتتر اپلیکیشن و ... میشود.
· تست خودکار
در زامارین شما میتوانید برای کدهای خود تست خودکار نوشته و آنها را به صورت خودکار تست کنید.
· Bind کردن Library های Objective-C و Java
زامارین طوری طراحی شدهاست که دست شما را در هیچگونه شرایطی نخواهد بست. شما میتوانید به صورت مستقیم کدهایی را که به زبان های Java و Objective-C نوشته شدهاند، به پروژه اضافه کرده و هیچگونه نگرانی از بابت کدهای از قبل نوشته شده که به زبانهای Objective-C و Java هستند، نداشته باشید.
· Designer
در زمارین این امکان وجود دارد که در هر پلتفرم از طریق Designer مخصوص به آن پلتفرم، UI خود را طراحی و پیاده سازی کنید.
· Async
در برنامه نویسی غیر همزمان ( Asynchronous Programming ) این امکان وجود دارد که برنامه شما بدون توقف، یک قسمت از کد را اجرا کرده و منتظر اجرای قسمتهای دیگر کد نشود؛ یا به اصطلاح برنامه از حالت Response خارج نشود. در زبانهای Java ، Objective-C و Swift اینکار باید با CallBack و به صورت Manual مدیریت شود؛ اما #C این امکان را فراهم آورده است که به راحتی اینکار را انجام داده و برنامه خود را همیشه در حالت پاسخ دهی نگه دارید.
public async Task<List<FeedItem>> GetFeedItems(DateTime date) { var feed = "http://planet.xamarin.com/feed/"; var response = await httpClient.GetStringAsync(feed); var items = await ParseFeedAsync(response); return items.Where(item => item.Published.Date == date).ToList(); }
· Parallel Programming
در برنامه نویسی موازی( Parallel Programming ) برخلاف برنامه نویسی MultiThread که بر روی یک هسته CPU اجرا میشود، بر روی چندین هسته CPU به صورت موازی اجرا میشود. زامارین از این نوع برنامه نویسی پشتیبانی میکند.
Xamarin.Forms: 2
پس از معرفی Xamarin Forms API شما میتوانید علاوه بر مزیتهایی که در بالا اشاره شد، کدهای Logic خود را با زبان C# و کدهای UI خود را با زبان XAML پیاده سازی کرده و با یک بار نوشتن کد، در پلتفرمهای مختلف خروجی خود را مشاهده کنید. مزیت استفاده از Xamarin Forms عبارتند از:
· استفاده از کد واحد برای پیاده سازی UI و Logic
یکی از بهترین مزیتهایی را که میتوان به آن اشاره نمود این است که شما کافیست یک بار کد خود را بنویسید و Xamarin Forms کد شما را در پلت فرمهای متفاوت پیاده سازی خواهد کرد.
<?xml version="1.0" encoding="UTF-8"?> <TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyApp.MainPage"> <TabbedPage.Children> <ContentPage Title="Profile" Icon="Profile.png"> <StackLayout Spacing="20" Padding="20" VerticalOptions="Center"> <Entry Placeholder="Username" Text="{Binding Username}"/> <Entry Placeholder="Password" Text="{Binding Password}" IsPassword="true"/> <Button Text="Login" TextColor="White" BackgroundColor="#77D065" Command="{Binding LoginCommand}"/> </StackLayout> </ContentPage> <ContentPage Title="Settings" Icon="Settings.png"> <!-- Settings --> </ContentPage> </TabbedPage.Children> </TabbedPage>
برای پیاده سازی UI در Xamarin Forms باید از XAML استفاده کنید. همچنین مانند روش قبلی میتوانید از زبان C# برای پیاده سازی منطق، استفاده نمایید.
با استفاده از Xamarin Forms شما تجربه نوشتن کد Cross Platform را در کنار Native بودن آن خواهید داشت.
· استفاده از یک کنترل مخصوص یک پلتفرم در بین کد ( Embedding )
در Xamarin Forms این امکان وجود دارد که اگر شما خواستید یک کنترل مخصوص IOS را در بین کدهای خود استفاده کنید، بتوانید به راحتی اینکار را انجام دهید.( (Embedding
اگر به تصویر بالا دقت کنید متوجه خواهید شد که در یکسری از کنترلها، تصاویر متفاوت هستند. در نسخه اندروید یک Action Button در قسمت پایین صفحه مشاهده میکنید که در نسخهی IOS آن موجود نیست. یعنی به صورت مستقیم کنترل Action Button که مختص به پلت فرم اندروید میباشد، درون Xamarin Forms استفاده شده است.
· دسترسی به هر پلتفرم به طور مستقیم
شما قادر خواهید بود به طور مستقیم به هر پلت فرم دسترسی پیدا کرده و به طور مثال در هر پلتفرم، UI مخصوص به خود را با Property های مخصوص به خود طراحی کنید.
· UITest و Test Cloud
در Xamarin Forms میتوانید برای UI خود تست نوشته و آنها را به وسیله Xamarin Test Cloud بر روی صدها Device متفاوت تست کنید. (این امکان فقط برای Android و IOS وجود دارد.)
· Life Cycle مشابه در تمامی پلتفرم ها
همانطور که میدانید پلتفرمهای مختلف، Life Cycle های متفاوتی برای مدیریت اپلیکیشن دارند. یکی از مزیتهای استفاده از Xamarin Forms این است که شما میتوانید برای تمامی پلتفرمها بهوسیلهی یک Life Cycle یکسان کد بنویسید.
· Previewer
یکی از بهترین قابلیتهایی که در Xamarin Forms اضافه شدهاست این است که شما قادر خواهید بود به صورت Real Time خروجی فایل XAML خود را به وسیله Previewer مشاهده نمایید.
· Performance Profiler
به وسیله Xamarin Profiler شما میتوانید میزان مصرف حافظه، Performance و ... را در اندروید و IOS اندازه گیری نمایید.
نکات قابل توجه:
Ø استفاده همزمان از Xamarin Forms و Xamarin Native
شما میتوانید کدهای خود را با حداکثر Reusability نوشته و در صورت لزوم با کدهای Xamarin Native ترکیب کنید.
Ø Documentation خیلی خوب
زمارین مستندات جامع و کاملی را در سایت خود گردآوری کرده که میتوانید به راحتی از آن برای فهم تمامی قسمتهای Xamarin استفاده کنید.
Delegate در سی شارپ
using System; using System.Windows.Forms; namespace CSharpDelegates { public delegate void Display(string sMsg); public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Display del = new Display(ShowMessage); del("This is an example for delegate"); } private void ShowMessage(string strMessage) { MessageBox.Show(strMessage); } } }
using System.Collections.Generic; namespace CSharpDelegates { public class Employee { public int EmployeeId { get; set; } public string Name { get; set; } public int Experience { get; set; } public double Salary { get; set; } public void IncreaseSalary(List<Employee> Employees) { foreach (Employee emp in Employees) { if (emp.Salary < 10000) { emp.Salary = emp.Salary + emp.Salary * 0.3; } } } } }
using System.Collections.Generic; namespace CSharpDelegates { public delegate bool SalaryIncreaseEligibility(Employee emp); public class Employee { public int EmployeeId { get; set; } public string Name { get; set; } public int Experience { get; set; } public double Salary { get; set; } public string IncreaseSalary(List<Employee> Employees, SalaryIncreaseEligibility del) { string sSalIncreasdEmployees = "Salary increased for "; foreach (Employee emp in Employees) { if (del(emp)) { emp.Salary = emp.Salary + emp.Salary * 0.3; sSalIncreasdEmployees = sSalIncreasdEmployees + emp.Name + " ,"; } } return sSalIncreasdEmployees; } } }
using System; using System.Collections.Generic; using System.Windows.Forms; namespace CSharpDelegates { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { List<Employee> empList = new List<Employee>(); empList.Add(new Employee() { EmployeeId = 100, Name = "Mark", Salary = 2000, Experience = 3 }); empList.Add(new Employee() { EmployeeId = 101, Name = "John", Salary = 15000, Experience = 8 }); empList.Add(new Employee() { EmployeeId = 102, Name = "David", Salary = 4000, Experience = 4 }); empList.Add(new Employee() { EmployeeId = 103, Name = "Bob", Salary = 50000, Experience = 14 }); empList.Add(new Employee() { EmployeeId = 104, Name = "Alex", Salary = 9000, Experience = 6 }); SalaryIncreaseEligibility del = new SalaryIncreaseEligibility(SalaryEligibility); Employee objEmp = new Employee(); string sMsg = objEmp.IncreaseSalary(empList, del); MessageBox.Show(sMsg); } private bool SalaryEligibility(Employee emp) { if (emp.Salary > 10000) { return true; } else { return false; } } } }
GitHub Issues
The GitHub Issues integration allows you to search and reference your issues from the commit message box in VS, in response to this suggestion ticket. You can reference an issue or a pull request by typing # or clicking on the # button in the lower right side of the commit message text box. If you weren't already authenticated to access related issues, you will now be prompted to sign in to take advantage of this feature.
Line Unstaging
To continue improving our line-staging (aka interactive staging) feature, we've added unstage. You can now use the tool tip option to unstage changes, line by line, as requested here Unstage individual lines and hunks in a file - 4 votes
Arm64
We continue to build native support for Arm64 on Windows 11 for the most popular developer scenarios. We now support the .NET Multi-platform App UI (MAUI) workload on Arm64 Visual Studio.
C++
- Available as a preview feature, you can now view Unreal Engine logs without leaving VS. To see the logs from the Unreal Engine Editor, click View > Other Windows > UE Log. To filter your logs, click on the "Categories" or "Verbosity" dropdowns. Since this is an experimental feature, feedback is greatly appreciated.
- You can now import STM32CubeIDE projects for embedded development within Visual Studio with File > Open > Import STM32CubeIDE project. This generates a CMake project with device flashing and debugging settings for STLink. You must have the STM32CubeIDE installed with the board support package for your device. More details available here.
- You can use the new CMake Debugger to debug your CMake scripts at build time. You can set breakpoints based on filenames, line numbers, and when CMake errors are triggered. Additionally, you can view call stacks of filenames and watch defined variables. Currently, this only works with bundled CMake, and projects targeting WSL or remote machines are not supported yet. We are actively working to add more support to the CMake debugger, and feedback is greatly appreciated.
مدیریت خطا در ASP.NET Core
کتاب رایگان LINQPad Succinctly
LINQPad Succinctly offers IT professionals a detailed examination of how and why LINQPad can improve development lifecycle and deliver applications in less time. Author José Roberto Olivas Mendoza begins with a detailed overview of LINQPad's features, then delves into the installation process, including necessary prerequisites. Readers then get instruction on how to get the most out of LINQPad, such as how to query data bases and using LINQPad as a code scratchpad, which allows users to save significant time and effort on application delivery.
- Introduction
- Installing LINQPad
- Beginning with LINQPad
- LINQPad Basics
- Querying Databases with LINQ-to-SQL
- LINQPad as a Code Scratchpad
- General Summary
- General Conclusions about LINQPad
- Appendix
تغییر مجوز ImageSharp به AGPL
ImageSharp, ImageSharp.Drawing, and ImageSharp.Web will all be dual licensed under a AGPLv3/Commercial license. The AGPLv3 license will come with exceptions which allow bundling the code alongside all well known open source licenses (Apache 2.0, MIT etc). Any projects seen as direct competition (Imaging SDKs) will not be able to utilize that exception.
یکی از سؤ برداشتهای متداول از کارهای سورس باز موجود این است:
«من مجازم از این کتابخانهی سورس باز هرجایی و هر طوری که دوست دارم استفاده کنم.»
در کل این یک «توهم» بزرگ است. بسته به مجوز پروژه (^)، جملهی فوق میتواند صحیح یا کاملا نادرست باشد.
برای نمونه من خیلیها رو میبینم که میگن: «از MySQL استفاده کن که رایگانه». نه دوست عزیز؛ اشتباه میکنید! فقط برای کارهای سورس باز رایگان است. مجوز نگارش Community و رایگان آن در ردهی مجوزهای GPL است (^). به این معنا که اگر روزی مطابق قوانین کپی رایت قرار شد رفتار شود، به سراغ کار سورس بسته شما که دارد از MySQL رایگان استفاده میکند، خواهند آمد. جهت اطلاع!
به همین جهت کسانی که کار تجاری سورس بسته انجام میدهند از طرف کتابخانههای دارای مجوز GPL حتی رد هم نمیشوند؛ چه برسد به اینکه بخواهند آزادانه از آن استفاده کنند.
در مورد مجوز کتابخانهی iTextSharp پیشتر مطلبی را در این سایت خواندهاید:
مجوز این کتابخانه، GNU Affero General Public License است. به این معنا که شما موظفید، تغییری در قسمت تهیه کننده خواص فایل PDF تولیدی که به صورت خودکار به نام کتابخانه تنظیم میشود، ندهید. اگر میخواهید این قسمت را تغییر دهید باید هزینه کنید. همچنین با توجه به اینکه این مجوز، GPL است یعنی زمانیکه از آن استفاده کردید باید کار خود را به صورت سورس باز ارائه دهید (^).
و ... نکته تکمیلی مهم اینکه:
این کتابخانه تا نگارش 4.1.7 تحت مجوز MPL/LGPL ارائه شده و «بدون مشکل» در کارهای تجاری سورس بسته قابل استفاده است. از نگارش 5 به بعد، AGPL شده و برای کارهای تجاری سورس بسته «رایگان نیست» (^).
برای نمونه سورس نسخه 4.1.7 از این آدرس قابل دریافت است.
این سورس را از پروژه "FDFToolkit .NET" اینجا نقل کردم چون تهیه کننده این پروژه دقیقا به این مطلب اشاره کرده و کار خود را به نگارش 4.1.7 کتابخانه iTextSharp عمدا محدود کرده است.