releasing-the-source-code
املای صحیح فناوریهای مرتبط با مایکروسافت
releasing-the-source-code
using System.ComponentModel.DataAnnotations; namespace NotifyPropertyChangedGenerator.Demo; public enum Gender { NotSpecified, [Display(Name = "مرد")] Male, [Display(Name = "زن")] Female }
public static class Extensions { public static string GetDisplayName(this Enum value) { if (value is null) throw new ArgumentNullException(nameof(value)); var attribute = value.GetType().GetField(value.ToString())? .GetCustomAttributes<DisplayAttribute>(false).FirstOrDefault(); if (attribute is null) return value.ToString(); return attribute.GetType().GetProperty("Name")?.GetValue(attribute, null)?.ToString(); } }
namespace NotifyPropertyChangedGenerator.Demo { public static class GenderExtensions { public static string GetDisplayName(this Gender @enum) { return @enum switch { Gender.NotSpecified => "NotSpecified", Gender.Male => "مرد", Gender.Female => "زن", _ => throw new ArgumentOutOfRangeException(nameof(@enum)) }; } } }
[Generator] public class EnumExtensionsGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) {} public void Execute(GeneratorExecutionContext context) { var compilation = context.Compilation; foreach (var syntaxTree in compilation.SyntaxTrees) { var semanticModel = compilation.GetSemanticModel(syntaxTree); var immutableHashSet = syntaxTree.GetRoot() .DescendantNodesAndSelf() .OfType<EnumDeclarationSyntax>() .Select(enumDeclarationSyntax => semanticModel.GetDeclaredSymbol(enumDeclarationSyntax)) .OfType<ITypeSymbol>() /*.Where(typeSymbol => typeSymbol.GetAttributes().Any( attributeData => string.Equals(attributeData.AttributeClass?.Name, "GenerateExtensions", StringComparison.Ordinal) ))*/ .ToImmutableHashSet(); foreach (var typeSymbol in immutableHashSet) { var source = GenerateEnumExtensions(typeSymbol); context.AddSource($"{typeSymbol.Name}Extensions.cs", source); } } }
private string GenerateEnumExtensions(ITypeSymbol typeSymbol) { return $@"namespace {typeSymbol.ContainingNamespace} {{ public static class {typeSymbol.Name}Extensions {{ public static string GetDisplayName(this {typeSymbol.Name} @enum) {{ {GenerateExtensionMethodBody(typeSymbol)} }} }} }}"; } private static string GenerateExtensionMethodBody(ITypeSymbol typeSymbol) { var sb = new StringBuilder(); sb.Append(@"return @enum switch { "); foreach (var fieldSymbol in typeSymbol.GetMembers().OfType<IFieldSymbol>()) { var displayAttribute = fieldSymbol.GetAttributes() .FirstOrDefault(attributeData => string.Equals(attributeData.AttributeClass?.Name, "DisplayAttribute", StringComparison.Ordinal)); if (displayAttribute is null) { sb.AppendLine( $@" {typeSymbol.Name}.{fieldSymbol.Name} => ""{fieldSymbol.Name}"","); } else { var displayAttributeName = displayAttribute.NamedArguments .FirstOrDefault(x => string.Equals(x.Key, "Name", StringComparison.Ordinal)) .Value; sb.AppendLine( $@" {typeSymbol.Name}.{fieldSymbol.Name} => ""{displayAttributeName.Value}"","); } } sb.Append( @" _ => throw new ArgumentOutOfRangeException(nameof(@enum)) };"); return sb.ToString(); }
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> </PropertyGroup> <Target Name="CleanSourceGeneratedFiles" BeforeTargets="BeforeBuild" DependsOnTargets="$(BeforeBuildDependsOn)"> <RemoveDir Directories="$(CompilerGeneratedFilesOutputPath)" /> </Target> <ItemGroup> <!-- Exclude the output of source generators from the compilation --> <Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" /> <Content Include="$(CompilerGeneratedFilesOutputPath)/**" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\NotifyPropertyChangedGenerator\NotifyPropertyChangedGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup> </Project>
{BaseIntermediateOutpath}/generated/{Assembly}/{SourceGeneratorName}/{GeneratedFile}
1.کش کردن همیشه آخرین حربه میباشد
2.حذف View Engineهای غیر ضروری
ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new RazorViewEngine());
ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new WebFormViewEngine());
3. استفاده از فایلهای PDB مایکروسافت برای دیباگ و یا پروفایل کردن DLLهای دیگران
با اینکه توصیه نامه W3C از پایان کار پیاده سازی این قابلیت خبر میدهد ولی در حال حاضر که این مقاله تدوین شده است هنوز نهایی اعلام نشده است. برای پشتیبانی مرورگرهای قدیمی از webstorage میتوان از فایل جاوااسکریپتی Store.js کمک گرفت.
مفاهیم امنیتی و محافظت از داده ها
محدودیتهای حمایتی و حفاظتی webstorage دقیقا همانند کوکی هاست. به این معنی که وب سایتهای دیگر توانایی اتصال به webstorage سایت دیگری را ندارند. البته این مورد ممکن است برای وب سایت هایی که بر ساب دومین تکیه کردهاند ایجاد مشکل کند. برای حل این مسائل میتوانید از کتابخانههای سورس بازی چون Cross Storage که توسط Zendesk ارائه شده است، استفاده کرد.
همانند هر مکانیزم ذخیره سازی سمت کلاینت، مواردی توصیه میگردد که رعایت آنها از لحاظ امنیتی پر اهمیت است. به عنوان نمونه ذخیرهی اطلاعات شخصی و موارد حساس توصیه نمیگردد؛ چرا که احتمال دسترسی آسان نفوذگران به دادههای محلی و خواندن آنها وجود دارد.
Data Integrity یا یکپارچگی دادهها نیز در نظر گرفته شده است. باید حفاظتی در برابر عدم موفقیت ذخیره سازی دادهها نیز وجود داشته باشد. این عدم موفقیتها میتواند به دلایل زیر رخ دهد:
IndexedDB
یکی از فرایندهای ذخیره سازی دادهها که همان مزایای webstorage را ارائه میدهد indexed Database API است. این قابلیت از HTML 5 اضافه شده است و قسمتی از مشخصات webstorage شناخته نمیشود. برای همین مستنداتی در حوزهی webstorage برای آن پیدا نخواهید کرد ولی قابلیتهایی فراتر از webstorage دارد.
این قابلیت پیچیدگی بیشتری را نسبت به خود webstorage ایجاد میکند، ولی فرصتهای بسیاری را برای ذخیره سازی دادههایی با معماریهای پیچیدهتر و رابطهها را میدهد. با استفاده از IndexedDB دادهها به شکل دیتابیسهای سمت سرور RDMS ذخیره میشوند و این قابلیت را دارید که به سمت آن کوئری هایی مشابه بانکهای اطلاعاتی سمت سرور را ارسال کنید.
در قسمت آتی نحوه کدنویسی آن را فرا خواهیم گرفت.
یک نکته: علت اینکه پروژههای ASP.NET Core به این صورت پویا عمل میکنند، وجود NET Core CLI. هست. این CLI هم شبیه به Angular-CLI یک ابزار خط فرمان است که کار ایجاد یک پروژهی جدید تا ساخت و توزیع برنامه را مدیریت میکند و در حقیقت VS فقط این فرامین خط فرمان را در پشت صحنه اجرا میکند. بنابراین بهتر است از ساختار پروژهای استفاده کنید که اساسا برای ابزارهای CLI طراحی شدهاست.