نظرات مطالب
شروع به کار با EF Core 1.0 - قسمت 11 - بررسی رابطه‌ی Self Referencing
آیا روش زیر برای پیاده‌سازی Self Referencing در حالی که هر عضو فقط صفر یا یک عضو فرزند می‌تواند داشته باشد، صحیح است؟
به نوعی پیاده‌سازی Self Referencing و  One-to-Zero-or-One  با هم:
public class EventItem
{
    public int Id { get; set; }

    public int? ParentId { get; set; }
    public virtual EventItem Parent { get; set; }

    public virtual EventItem Alternative { get; set; }
}
public class EventItemConfiguration : IEntityTypeConfiguration<EventItem>
{
    public void Configure(EntityTypeBuilder<EventItem> builder)
    {
        builder.HasIndex(e => e.ParentId);
        builder.HasOne(e => e.Parent)
            .WithOne(e => e.Alternative)
            .HasForeignKey<EventItem>(e => e.ParentId);
    }
}

مطالب
AOP و پردازش فراخوانی‌های تو در تو
هنگامی‌که از روش AOP استفاده می‌کنیم گاهی نیاز است متد تزیین‌شده را از متدی درون خود کلاس فراخوانی کنیم و می‌خواهیم aspectهای آن متد نیز فراخوانی شوند.

پیش‌نیازدوره‌ی AOP
(برای سادگی کار از تعریف attribute خودداری کردم. شما می‌توانید با توجه به آموزش، attributeهای دلخواه را به متدها بیافزایید).
Interface و کلاس پیاده‌سازی‌شده‌ی آن در لایه سرویس:
public interface IMyService 
{ 
  void foo();
  void bar();
}

public class MyService : IMyService
{
  public void foo()
  {
    Console.Write("foo");
    bar();
  }

  public void bar()
  {
    Console.Write("bar");
  }
}
نام متد در خروجی نوشته می‌شود. همچنین می‌خواهیم پیش از فراخوانی این متد‌ها، متنی در خروجی نوشته شود.

آماده‌سازی Interceptor
یک interceptor ساده که نام متد را در خروجی می‌نویسد.
//using Castle.DynamicProxy;

public class Interceptor : IInterceptor 
{
  public void Intercept(IInvocation invocation)
  {
    Console.WriteLine("Intercepted: " + invocation.Method.Name);
    invocation.Proceed();
  }
}

معرفی Interceptor به سیستم
همانند قبل:
//using System;
//using Castle.DynamicProxy;
//using StructureMap;

class Program
    {
        static void Main(string[] args)
        {
            ObjectFactory.Initialize(x =>
            {
                var dynamicProxy = new ProxyGenerator();
                x.For<IMyService>()
                 .EnrichAllWith(myTypeInterface => 
                                     dynamicProxy.CreateInterfaceProxyWithTarget(myTypeInterface, new Intercept()))
                 .Use<MyService>();
            });
 
            var myService = ObjectFactory.GetInstance<IMyService>();
            myService.foo();
        }
    }

انتظار ما این است که خروجی زیر تولید شود:
Intercepted foo
foo
Intercepted bar
bar
اما نتیجه این می‌شود که دلخواه ما نیست:
Intercepted foo
foo
bar

راه‌حل
برای حل این مشکل دو کار باید انجام داد:
1- متد تزیین‌شده باید virtual باشد.
public class MyService : IMyService
{
  public virtual void foo()
  {
    Console.Write("foo");
    bar();
  }

  public virtual void bar()
  {
    Console.Write("foo");
    bar();
  }
}
2- شیوه معرفی متد به سیستم باید به روش زیر باشد:
// جایگزین روش پیشین در متد Main
x.For<IMyService>()
                    .EnrichAllWith(myTypeInterface  => dynamicProxy.CreateClassProxy<MyService>(new Intercept()))                    
                    .Use<MyService>();

دلیل این مسئله به دو روش proxy برمی‌گردد که برای اطلاع بیشتر به مستندات پروژه Castle مراجعه کنید.
در این‌جا روش Inheritance-based به کار رفته است. در این روش، تنها متدهای virtual را می‌توان intercept کرد. در روش پیشین(Composition-based) برای همه‌ی متدها عملیات intercept انجام می‌شد (کلاس proxy پیاده‌سازی‌شده‌ی interface ما بود) که در این‌جا این‌گونه نیست و می‌تواند به سرعت برنامه کمک کند.
نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 6 - سرویس‌ها و تزریق وابستگی‌ها
چگونگی معرفی و استفاده از یک اینترفیس در صورتی که چند کلاس  پیاده ساز داشته باشد : 
اینترفیس IMultiple و دو کلاس پیاده سازی کننده : 
    public interface IMultiple {
        string GetName ();
    }

    public class ImplementationOne : IMultiple {
        public string GetName () {
            return "Abolfazl Roshanzamir";
        }
    }

    public class ImplementationTwo : IMultiple {
        public string GetName () {
            return "َAndy Madadian";
        }
    }
ثبت سرویس : 
            services.AddScoped<ImplementationOne> ();
            services.AddScoped<ImplementationTwo> ();
            services.AddScoped<Func<string, IMultiple>> (serviceProvider => key => {
                switch (key) {
                    case "A":
                        return serviceProvider.GetService<ImplementationOne> ();
                    case "B":
                        return serviceProvider.GetService<ImplementationTwo> ();
                    default:
                        throw new KeyNotFoundException (); // or maybe return null, up to you
                }
            });

استفاده از سرویس همراه با مشخص کردن پیاده ساز مورد نظر
private readonly Func<string, IMultiple> _serviceAccessor;

public HomeController (Func<string, IMultiple> serviceAccessor) {
     this._serviceAccessor = serviceAccessor;
}
public IActionResult Index () {
    var implementOne = this._serviceAccessor ("A").GetName (); // Abolfazl Roshanzamir 
    var implementTwo = this._serviceAccessor ("B").GetName (); // Andy Madadian 
    return View ();
}

 
مطالب
ساخت ربات تلگرامی با #C
 با رشد دنیای تکنولوژی، وسائل هوشمند همراه نیز به سرعت پیشرفته‌تر شدند. در این میان با گسترش زیرساخت اینترنت، رشد شبکه‌های اجتماعی نیز چشمگیر بوده است. یکی از بهترین این‌ها، شبکه‌های تلگرام می‌باشد که با بهره گیری از سرورهای ابری، امنیت و سرعت را برای کاربران به ارمغان آورده است.
چندی پیش موسسان تلگرام با معرفی API‌های کاربردی، به توسعه کنندگان اجازه دادند که با بهره گیری از بستر این شبکه، اقدام به تولید اینترفیسی به اسم بات کنند که با دریافت دستورات سفارشی، عملیات خاصی را انجام دهد.
در واقع تلگرام و متدهای ارائه شده، یک راه ارتباطی بین کاربران و برنامه‌های تولید شده را ایجاد کردند که با قدری ذوق و سلیقه، شاهد بات‌های جالب و کاربردی هستیم.
در این مقاله سعی شده طرز تهیه یک بات با زبان #C توضیح داده شود.
در ابتدا شما باید توسط یکی از بات‌های اصلی تلگرام اقدام به ثبت نام کاربری و تنظیمات بات مورد نظر خودتان نمایید. بات مورد نظر @BotFather می‌باشد که با شروع مکالمه می‌توان با فرستادن دستورات مختلف تنظیمات مختلفی را انجام داد. با شروع مکالمه با بات مورد نظر با دستور /start دستورات زیر قابل انجام می‌باشد:

 You can control me by sending these commands :

/ newbot - create a new bot

/ token - generate authorization token

/ revoke - revoke bot access token

/ setname - change a bot's name

/ setdescription - change bot description

/ setabouttext - change bot about info

/ setuserpic - change bot profile photo

/ setcommands - change bot commands list

/ setjoingroups - can your bot be added to groups ?

/ setprivacy - what messages does your bot see in groups ?

/ deletebot - delete a bot

/ cancel - cancel the current operation
با انجام دستور /newbot در ابتدا نام بات و یوزنیم (دقت کنید یوزرنیم می‌بایست حتما به کلمه‌ی bot ختم شود) را تنظیم کنید.
بعد از تایید نام و یوزر نیم، به شما یک توکن اختصاص داده می‌شود که توسط آن شما شناسایی می‌شوید.
در اینجا شما می‌توانید تنظیمات اضافه‌تری مانند عکس برای پروفایل و غیره را نیز تنظیم کنید.
در مرحله‌ی بعد می‌توانید در همین قسمت دستورات مورد نظر را جهت بات خود تنظیم کنید. برای این کار باید دستور /setcommands را وارد کنید و دستور مورد نظر خود را به فرمت command1 – Description وارد کنید.
مرحله‌ی بعد، تنظیمات برنامه‌ی شما جهت دریافت دستورات وارد شده و انجام عملیات مورد نظر و تولید و ارسال خروجی مورد نظر است.

دریافت دستورات به دو طریق انجام می‌شود:
1. توسط دستور getUpdates می‌توان تمامی کامندهای دریافتی را از سرور تلگرام دریافت کرد و با انجام پروسس‌های لازم، خروجی را به کاربر مورد نظر ارسال کرد.
2. توسط تابع webhook از تلگرام درخواست کرد در صورت دریافت دستور جدید به بات، این دستور را به یک آدرس خاص ارسال کرد.

قابل توجه است که می‌توان فقط از یکی از دو روش فوق استفاده کرد. همچنین در روش دوم حتما سرور مورد نظر باید گواهی ssl تایید شده داشته باشد.
کد زیر دریافت کامندهای یک بات به روش اول می‌باشد :
public class mydata
    {
        public result[] result;
    }
    public class result
    {
        public int update_id { get; set; }
        public message message { get; set; }
    }
    public class message
    {
        public int message_id { get; set; }
        public message_from from { get; set; }
        public message_chat chat { get; set; }
        public int date { get; set; }
        public string text { get; set; }
    }
    public class message_from
    {
        public int ind { get; set; }
        public string first_name { get; set; }
        public string username { get; set; }
    }
    public class message_chat
    {
        public int id { get; set; }
        public string first_name { get; set; }
        public string username { get; set; }
    }
 
public  Void GetUpdates()
        {
 
            WebRequest req = WebRequest.Create("https://api.telegram.org/bot" + yourToken + "/getUpdates");
            req.UseDefaultCredentials = true;
            WebResponse resp = req.GetResponse();
            Stream stream = resp.GetResponseStream();
            StreamReader sr = new StreamReader(stream);
            string s = sr.ReadToEnd();
            sr.Close();
            var jobject = Newtonsoft.Json.Linq.JObject.Parse(s);
            mydata gg = JsonConvert.DeserializeObject<mydata>(jobject.ToString());
            List<result> results = new List<result>();
            foreach (result rs in gg.result)
            {
                results.Add(rs); 
                SendMessage(rs.message.chat.id.ToString(), "hello"+" "+"Dear"+rs.message.chat.first_name); 
            }             
        }
و توسط تابع زیر می‌توان به کاربری که به بات کامند ارسال کرد، پاسخ داد:
public static void SendMessage(string chat_id, string message)
        {
            WebRequest req = WebRequest.Create("https://api.telegram.org/bot" + youToken + "/sendMessage?chat_id=" + chat_id + "&text=" + message);
            req.UseDefaultCredentials = true;
 
            var result = req.GetResponse();
            req.Abort();
        }

لازم به ذکر است خروجی توابع بات‌های تلگرام با فرمت JSON می‌باشد که با نصب پکیج NewTonsoft می‌توان آن را به لیست تبدیل کرد.
rs.message.chat.id، آی دی فردی است که به بات تلگرامی ما مسیج ارسال کرده است.
rs.message.chat.first_name نام فردی است که به بات تلگرام مسیج ارسال کرده است.
همچنین می‌توان در جواب کامند بات، علاوه بر متن، صدا و تصویر را نیز ارسال نمود .

در این لینک و این لینک می‌توان توضیحات بیشتری را در این زمینه مطالعه کرد.
در انتها خوشحال می‌شوم ذوق‌ها و ایده‌های شما را در ساخت بات‌ها با آیدی @iekhtiari مشاهده کنم.
مطالب
هاست سرویس های Asp.Net Web Api با استفاده از OWIN و TopShelf
زمانیکه از Template‌های پیش فرض تدارک دیده شده در VS.Net برای اپلیکیشن‌های وب خود استفاده می‌کنید، وب اپلیکیشن و سرور با هم یکپارچه هستند و تحت IIS  اجرا می‌شوند. به وسیله Owin می‌توان این دو مورد را بدون وابستگی به IIS به صورت مجزا اجرا کرد. در این پست قصد داریم سرویس‌های Web Api را در قالب یک Windows Service با استفاده از کتابخانه‌ی TopShelf هاست نماییم.
پیش نیاز ها:
»Owin چیست
»تبدیل برنامه‌های کنسول ویندوز به سرویس ویندوز ان تی

  برای شروع یک برنامه Console Application ایجاد کرده و اقدام به نصب پکیج‌های زیر نمایید:
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Install-Package TopShelf

حال یک کلاس Startup برای پیاده سازی Configuration‌های مورد نیاز ایجاد می‌کنیم
در این قسمت می‌توانید تنظیمات زیر را پیاده سازی نمایید:
»سیستم Routing؛
»تنظیم  Dependency Resolver برای تزریق وابستگی کنترلر‌های Web Api؛
»تنظیمات hub‌های SignalR(در حال حاضر SignalR به صورت پیش فرض نیاز به Owin برای اجرا دارد)؛
»رجیستر کردن Owin Middleware‌های نوشته شده؛
»تغییر در Asp.Net PipeLine؛
»و...

public class Startup 
    {       
        public void Configuration(IAppBuilder appBuilder) 
        {          
            HttpConfiguration config = new HttpConfiguration(); 
            config.Routes.MapHttpRoute( 
                name: "DefaultApi", 
                routeTemplate: "api/{controller}/{id}", 
                defaults: new { id = RouteParameter.Optional } 
            ); 

            appBuilder.UseWebApi(config); 
        } 
    }
* به صورت پیش فرض نام این کلاس باید Startup و نام متد آن نیز باید Configuration باشد.

در این مرحله یک کنترلر Api به صورت زیر به پروژه اضافه نمایید:
public class ValuesController : ApiController 
    {        
        public IEnumerable<string> Get() 
        { 
            return new string[] { "value1", "value2" }; 
        } 
      
        public string Get(int id) 
        { 
            return "value"; 
        } 

        public void Post([FromBody]string value) 
        { 
        } 

        public void Put(int id, [FromBody]string value) 
        { 
        }        
    }
کلاسی به نام ServiceHost ایجاد نمایید و کد‌های زیر را در آن کپی کنید:
public class ServiceHost
    {     
        private IDisposable webApp;             

        public static string BaseAddress 
        {
            get
            {
                return "http://localhost:8000/";
            }
        }

        public void Start()
        {           
            webApp = WebApp.Start<Startup>(BaseAddress);          
        }

        public void Stop()
        {           
            webApp.Dispose();          
        }
    }
واضح است که متد Start در کلاس بالا با استفاده از متد Start کلاس WebApp، سرویس‌های Web Api را در آدرس مورد نظر هاست خواهد کرد. با فراخوانی متد Stop این سرویس‌ها نیز dispose خواهند شد.
در مرحله آخر باید شروع و توقف سرویس‌ها را تحت کنترل کلاس HostFactory کتابخانه TopShelf در آوریم. برای این کار کافیست کلاسی به نام ServiceHostFactory ایجاد کرده و کد‌های زیر را در آن کپی نمایید:
public class ServiceHostFactory
    {
        public static void Run()
        {
            HostFactory.Run( config =>
            {
                config.SetServiceName( "ApiServices" );
                config.SetDisplayName( "Api Services ]" );
                config.SetDescription( "No Description" );

                config.RunAsLocalService();

                config.Service<ServiceHost>( cfg =>
                {
                    cfg.ConstructUsing( builder => new ServiceHost() );

                    cfg.WhenStarted( service => service.Start() );
                    cfg.WhenStopped( service => service.Stop());
                } );
            } );
        }
    }
توضیح کد‌های بالا:
ابتدا با فراخوانی متد Run سرویس مورد نظر اجرا خواهد شد. تنظیمات نام سرویس و نام مورد نظر جهت نمایش  و همچنین توضیحات در این قسمت انجام می‌گیرد.
با استفاده از متد ConstructUsing عملیات وهله سازی از سرویس انجام خواهد گرفت. در پایان نیز متد Start  و Stop کلاس ServiceHost، به عنوان عملیات شروع و پایان سرویس ویندوز مورد نظر تعیین شد.

حال اگر در فایل Program پروژه، دستور زیر را فراخوانی کرده و برنامه را ایجاد کنید خروجی زیر قابل مشاهده است.
ServiceHostFactory.Run();

در حالیکه سرویس مورد نظر در حال اجراست، Browser را گشوده و آدرس http://localhost:8000/api/values/get را در AddressBar وارد کنید. خروجی زیر را مشاهده خواهید کرد:

اشتراک‌ها
Async Main در C# 7.1
In C# 7.1, the language extends the valid signatures of an entrypoint to allow these async overloads of the Main method to be valid.

public static void Main();
public static int Main();
public static void Main(string[] args);
public static int Main(string[] args);
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
Async Main در C# 7.1
مطالب
نحوه ایجاد الگوی Singleton به صورت جنریک
در برخی از مواقع، ایجاد یک وهله از یک کلاس کاری هزینه بر می‌باشد. بنابراین نیاز است تا فقط یک وهله از آن کلاس را ایجاد و تا آخر اجرای برنامه از آن استفاده کرد. این راه حل در قالب یک الگوی طراحی به نام Singleton معرفی شده است. حال می‌خواهیم با استفاده از امکانات جنریک، کلاسی را طراحی کنیم تا عملیات ساخت وهله‌ها را انجام دهد.
نکاتی که در طراحی یک الگوی Singleton باید مد نظر داشت این است که:
  1. دسترسی سازنده کلاس Singleton را از نوع Private تعیین کنیم.
  2. یک فیلد استاتیک از نوع کلاس Singleton تعریف کنیم.
  3. یک خاصیت از نوع استاتیک فقط خواندنی (یعنی فقط get داشته باشد) تعریف کرده تا فیلد استاتیک را مقداردهی و Return کند. به جای پروپرتی میتوان از یک متد استاتیک نیز استفاده کرد.
public class SingletonClassCreator<T> where T:class , new()
    {
        private static T _singletoneInstance;
        private static readonly object Lock = new object();

        public static T SingletoneInstance
        {
            get
            {
                lock (Lock)
                {
                    if (_singletoneInstance == null)
                    {
                        _singletoneInstance = new T();                        
                    }
                }
                return _singletoneInstance;
            }            
        }

        private SingletonClassCreator()
        {            
        }
    }
برای ایجاد حالت Tread-Safe در برنامه هایی که امکان دسترسی همزمان به یک شیء (مثلا در برنامه‌های وب) وجود دارد، از یک بلاک Lock استفاده شده است تا در هر لحظه فقی یک نخ قادر به ایجاد Singleton شود.
حال برای ایجاد وهله‌های Singleton از کلاسهای مورد نظر به صورت زیر عمل میکنیم
public class FirstSingleton
    {
        public int Square(int input)
        {
            return input*input;
        }
    }
static void Main(string[] args)
        {            
            var firstSingletone = SingletonClassCreator<FirstSingleton>.SingletoneInstance ;
            Console.WriteLine(firstSingletone.Square(12));            
            Console.ReadKey();
        }
در خط اول، با تعریف یک متغیر و قرار دادن وهله استاتیک که بوسیله پروپرتی استاتیک SingletoneInstance برگشت داده میشود، یک شی Singleton از کلاس FirstSingleton را ایجاد میکنیم.
اشتراک‌ها
انجمن رسمی گزارش مشکلات GitHub

GitHub Community is built to support all GitHub users on their educational journey, via Discussions. It is a resource hub, learning portal, and inspiration station, all in one. Regardless of how big or small your challenge is, all resources and information will be accessible in a true open source fashion.

انجمن رسمی گزارش مشکلات GitHub