Git for Windows 2.19.0 منتشر شد
New Features
Comes with Git v2.19.0.
There are now fast, built-in versions of git stash and git rebase, available as experimental options.
The included OpenSSH client now enables modern ciphers.
The gitweb component was removed because it is highly unlikely to be used on Windows.
The git archimport tool (which was probably used by exactly 0 users) is no longer included in Git for Windows.
The ASP.NET Core tag helpers improve on the HTML templated helpers in ASP.NET MVC 5. ASP.NET Core comes with some useful stock tag helpers for common tasks such as creating custom elements or extending existing HTML elements, but their use can be extended to making a framework such as Bootstrap easier to work with. Dino shows how helpers are used, and demonstrates a Bootstrap Modal Tag Helper
Rider EAP 20 منتشر شد.
Rider EAP 20 fixes a number of bugs, improves .NET Core support, has better NuGet performance, supports Xamarin Android applications, comes with Node.js tooling from WebStorm (including SpyJS), can generate ResX files, executes T4 templates (needs Windows and Visual Studio SDK), adds support for scratch files, … Too much for one sentence, as you can see from the full list of fixes. We’ll highlight a few, read on!
AngularJs و i18n
The new i18n story in Angular
Internationalization support in Angular has been very poor so far. You might know that there’s anngLocale
module you need to include, which is used by a couple components, likengPluralize
,date
andcurrency
filter to name a few, and that’s pretty much it. As we’ve already discussed, there’s so much more that comes into play when internationalizing an application, which is why there’s finally a new solution evolving that will bring first-class i18n support to the Angular framework.
evernote – مرتبسازی مبتنی بر برچسب
- اضافه کردن اسمبلیها به صورت دستی به پروژه و تنظیم Build Action آنها به Embedded Resource
- تنظیم فایل csproj پروژه برای Embed کردن خودکار رفرنسهای پروژه در زمان Build
روش اول
روش دوم
<Target Name="EmbedReferencedAssemblies" AfterTargets="ResolveAssemblyReferences"> <ItemGroup> <AssembliesToEmbed Include="@(ReferenceCopyLocalPaths)" /> <EmbeddedResource Include="@(AssembliesToEmbed)" Condition="'%(AssembliesToEmbed.Extension)' == '.dll'"> <LogicalName>%(AssembliesToEmbed.DestinationSubDirectory)%(AssembliesToEmbed.Filename)%(AssembliesToEmbed.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> <Message Importance="high" Text="Embedding: @(AssembliesToEmbed->'%(DestinationSubDirectory)%(Filename)%(Extension)', ', ')" /> </Target> <Target Name="DeleteAllReferenceCopyLocalPaths" AfterTargets="Build"> <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" /> </Target>
همانطور که در تصویر بالا نیز مشاهده میکنید، اسمبلیهای ارجاعی برنامه TestApp به صورت Resource به آن اضافه شدهاند.
نحوه بارگذاری اسمبلیهای Embed شده
در پروژههای WPF، در OnStartup event کلاس App و در پروژههای WinForm در متد Main کلاس Program، قطعه کد زیر را وارد میکنیم:
private void App_OnStartup( object sender, StartupEventArgs e ) { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; var assembly = Assembly.GetExecutingAssembly(); foreach (var name in assembly.GetManifestResourceNames()) { if ( name.ToLower() .EndsWith( ".resources" ) || !name.ToLower() .EndsWith( ".dll" ) ) continue; EmbeddedAssembly.Load( name, name ); } } static Assembly OnResolveAssembly( object sender, ResolveEventArgs args ) { var fields = args.Name.Split( ',' ); var name = fields[0]; var culture = fields[2]; if ( name.EndsWith( ".resources" ) && !culture.EndsWith( "neutral" ) ) return null; return EmbeddedAssembly.Get( args.Name ); }
با استفاده از رویداد AssemblyResolve می توان اسمبلی Embed شده را در زمانیکه نیاز به آن است، بارگذاری کرد. کد مربوط به کلاس EmbeddedAssembly نیز به این صورت میباشد:
using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Security.Cryptography; public static class EmbeddedAssembly { static Dictionary< string, Assembly > _dic; public static void Load( string embeddedResource, string fileName ) { if ( _dic == null ) _dic = new Dictionary< string, Assembly >(); byte[] ba; Assembly asm; var curAsm = Assembly.GetExecutingAssembly(); using ( var stm = curAsm.GetManifestResourceStream( embeddedResource ) ) { if ( stm == null ) return; ba = new byte[(int)stm.Length]; stm.Read( ba, 0, (int)stm.Length ); try { asm = Assembly.Load( ba ); _dic.Add( asm.GetName().Name, asm ); return; } catch { } } bool fileOk; string tempFile; using ( var sha1 = new SHA1CryptoServiceProvider() ) { var fileHash = BitConverter.ToString( sha1.ComputeHash( ba ) ) .Replace( "-", string.Empty ); tempFile = Path.GetTempPath() + fileName; if ( File.Exists( tempFile ) ) { var bb = File.ReadAllBytes( tempFile ); var fileHash2 = BitConverter.ToString( sha1.ComputeHash( bb ) ) .Replace( "-", string.Empty ); fileOk = fileHash == fileHash2; } else { fileOk = false; } } if ( !fileOk ) { File.WriteAllBytes( tempFile, ba ); } asm = Assembly.LoadFile( tempFile ); _dic.Add( asm.GetName().Name, asm ); } public static Assembly Get( string assemblyFullName ) { if ( _dic == null || _dic.Count == 0 ) return null; var name = new AssemblyName( assemblyFullName ).Name; return _dic.ContainsKey( name ) ? _dic[name] : null; } }
با استفاده از متد Load کلاس بالا، کل اسمبلیهایی که بارگذاری شدهاند در یک دیکشنری استاتیک نگهداری میشوند. ابتدا اسمبلیها را با استفاده از []byte بارگذاری میکنیم و در صورتیکه بارگذاری اسمبلی با خطایی مواجه شود، بارگذاری را با استفاده از فایل temp انجام میدهیم (که معمولا برای فایلهای unmanaged این مورد اتفاق میافتد).
با استفاده از متد Get که در زمان نیاز به یک اسمبلی توسط AssemblyResolve فراخوانی میشود، اسمبلی مربوطه از دیکشنری پیدا شده و برگشت داده میشود.
نکته ها
- در صورتیکه بخواهید فایلی را از Embed کردن خودکار (روش دوم) استثناء کنید، باید از Condition استفاده کنید:
<Target Name="EmbedReferencedAssemblies" AfterTargets="ResolveAssemblyReferences"> <ItemGroup> <AssembliesToEmbed Include="@(ReferenceCopyLocalPaths)" /> <EmbeddedResource Include="@(AssembliesToEmbed)" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(AssembliesToEmbed.Filename)', '^((?!Microsoft).)*$')) And '%(AssembliesToEmbed.Extension)' == '.dll'"> <LogicalName>%(AssembliesToEmbed.DestinationSubDirectory)%(AssembliesToEmbed.Filename)%(AssembliesToEmbed.Extension)</LogicalName> </EmbeddedResource> </ItemGroup> <Message Importance="high" Text="Embedding: @(AssembliesToEmbed->'%(DestinationSubDirectory)%(Filename)%(Extension)', ', ')" /> </Target> <Target Name="DeleteAllReferenceCopyLocalPaths" AfterTargets="Build"> <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(Filename)', '^((?!Microsoft).)*$')) Or '%(Extension)' == '.xml'" /> </Target>
- در صورتیکه بعد از اجرای برنامه و یا اجرای به صورت دیباگ با خطای Stackoverflow مواجه شدید که به خاطر ارجاعات زیاد Resourceهای برنامه پیش میآید، کد زیر را به فایل AssemblyInfo، در پوشه Properties اضافه کنید:
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)]
- در صورتیکه پروژه شما از نوع Office Add-Ins باشد، باید در کد مربوط به AssemblyResolve را در فایل ThisAddIn.Designer.cs (در صورت عدم تغییر نام) به متد Initialize اضافه کنید و دستور بارگذاری را در متد ThisAddIn_Startup اضافه کنید. نکته خیلی مهم: در فایل csproj حتما در قسمت Condition باید اسمبلیهایی را که با نام Microsoft شروع میشوند، از Embed شدن استثناء کنید و در قسمت DeleteAllReferenceCopyLocalPaths مقدار "AfterTargets="VisualStudioForApplicationsBuild را قرار دهید (تا امکان Build پروژه برای شما باشد) و همچنین پسوند vsto را نیز نباید حذف کنید.