نظرات مطالب
EF Code First #11
سلام ، 

ذکر کردید "بهتر است یک لایه ی اضافی به نام سرویس ایجاد شود و اعمال مربوط به EF را به آن منتقل نمود" یعنی به ازای هر موجودیت یک سرویس هم داشته باشیم ؟ این (http://pastebin.com/iUCn1303) نمونه کدی که اینجا قرار دادم صحیح است ؟ -Service همان Business logic ما خواهد بود ؟ یعنی علاوه بر اعمال CRUD ، بررسی منطق تجاری ، Validate کردن Entity و یا اعمال شرط های مختلف در Query ها در همین لایه ی سرویس انجام می شود ؟   
-اگر بخواهیم اطلاعات User را با اطلاعات پروفایل در قالب یک لیست برای لایه ی پایین تر بفرستیم ، نوع خروجی چه باید باشد ؟ مثلا UserProfileDataTransferObject ؟ 

در سری هشتم Refactoring در مورد God Classes توضیح دادید.  برای منطق های پیچیده روی یک Enity مثل User مثلا چندین Query با حالت های مختلف کلاس UserService به God Class تبدیل می شود. راه حل چیست ؟ اگر ممکن است پروژه ی کد باز مورد تایید خودتون برای مرور کد ها معرفی کنید. 
خیلی ممنون
نظرات مطالب
بهبود SEO در ASP.NET MVC
- تشخیص وجود کوئری استرینگ در یک Url، حالت دیگری نمی‌تونه داشته باشه.
- ضمنا یک Url می‌تونه کوئری استرینگی با چندین name-value داشته باشه. ضرورتی به بررسی تمام موارد و کند کردن کار نیست که آیا مقدار دارند همگی یا خیر.
مطالب
رویدادها در jQuery
Jquery یکی از کتابخانه‌های قدرتمند JavaScript است که به طور وسیعی مورد استفاده طراحان وب قرار میگیرد. این کتابخانه از سه دیدگاه بسیار سودمند است؛ ابتدا به دلیل مدیریت قدرتمند Dom که دارد و دوم اینکه ارتباط Ajax را بسیار راحت کرده است و هم اینکه بستر پلاگین نویسی را فراهم ساخته است، به طوری که میلیون‌ها کتابخانه ثالث از روی همین کتابخانه ایجاد شده است. زمانیکه شما به مطالعه این کتابخانه رو آورید و نمونه کدهای مختلفی از آن را بر روی شبکه اینترنت ببینید، ممکن است این کتابخانه در عین سادگی که دارد، ابهاماتی را برای شما ایجاد کند که یکی از آن‌ها نحوه استفاده از رویدادهاست. لیست زیر نمونه‌ای از نحوه رویداد نویسی در جی کوئری است:
$().click(fn)
$().bind('click',fn)
$().live('click',fn)
$().delegate(selector, 'click', fn)
$().on('click',fn);
$().on('click', selector ,fn);
دو مورد اول در لیست، یکی هستند و در واقع مورد اول یک میانبر برای مورد دوم محسوب میشود و در پشت صحنه در واقع همان خط دوم مورد استفاده قرار میگیرد. از مزایایی که در مورد bind نسبت به استفاده مستقیم از اسم رویداد میتوان گفت این است که میتواند در یک زمان به چند رویداد متصل شود. به عنوان مثال کد زیر نمونه‌ای از آن است:
    $(".test").bind( "click mouseover mouseout", function() { console.log('fired!') } );
در خط بالا المان‌هایی که با کلاس test مزین گشته‌اند، به سه رویداد و یک تابع بایند یا متصل گشته‌اند. برای غیرفعال سازی این رویدادها میتوان از متد unbind استفاده کرد:
$(".test").unbind( "click");
برای استفاده از این دو حالت باید در نظر گرفت که تنها المان‌هایی به این رویداد متصل یا بایند میگردند که در زمان بررسی DOM، یعنی بارگذاری اولیه سایت وجود داشته‌اند و در صورتیکه المان جدیدی به صفحه اضافه شود یا اینکه جایگزین المان دیگری شود، بایند نخواهند شد و تنها المان‌های قدیمی کار خواهند کرد و در صورتیکه المانی از روی صفحه حذف شود، این اتصال از بین خواهد رفت.

مورد سوم، متد معروف live است که هم بر روی المان‌های قدیمی و هم بر روی المان‌های جدید جواب میدهد. ولی نکته‌ای که در مورد live وجود دارد این است که در نسخه‌های اخیر به دلیلی که در جلوتر عنوان میشود حذف شده است و دیگر وجود ندارد. دلیل این حذف هم این میباشد که در واقع متد live برای اینکه افزوده شدن المان‌های جدید را زیر نظر بگیرد، به خود المان متصل نمیشود؛ بلکه به به کل سند HTML یا بدنه وب سایت متصل میشد و کل ناحیه را مورد بررسی قرار میداد تا اگر المان جدیدی اضافه شد، بتواند رویداد مرتبطی را بر روی آن اجرا کند. همچنین در این حالت رویدادی‌هایی از این نوع، در اجداد این المان نیز اجرا میگردند. یعنی رویداد، از المان آغاز شده، سپس به سمت اجدادش انتقال خواهد یافت (به این حالت Bubbling up گفته میشود). پس برای اینکه این ناحیه کوچک‌تر و جزئی‌تر شود، متد دیگری جایگزین آن شد؛ به نام delegate:
$("#area").delegate('.test','click',function(e){...});

----------------------------------------
<div id="area">
<span>Span1</span>
<span>Span2</span>
</div>
این حالت که جایگزین حالت قبلی شده است بدین صورت است که ناحیه‌ای با آی دی area وجود دارد که المان‌هایی با کلاس test در آن قرار میگیرند. پس، از این به بعد، بجای اینکه کل سند بررسی شود، فقط همین بخش مورد بررسی قرار میگیرد و رویداد کلیک، بر روی المانی با کلاس test اجرا میشود و bubbling up کمتری خواهیم داشت و میتوان آن را کنترل کرد. برای حذف رویدادهای live از المان‌های مربوطه، میتوان از die و برای delegate از undelegate همانند unbind استفاده کرد. همچنین حالت استفاده از زنجیره‌ای از متدها در متد live در نظر نگرفته شده، ولی بعد از دلیگیت میتوان از متدهای دیگر، به صورت زنجیره‌ای استفاده کرد.

 از نسخه 1.7 به بعد  توصیه شده‌است به جای تمامی متدهای بالا،  از on استفاده شود که به مراتب کارآایی بهتری دارد و اکثر این متدهای بالا، حذف یا منسوخ شده اعلام گشته‌اند و احتمال حذف آن‌ها در نسخه آتی وجود دارد. به عنوان مثال delegate از نسخه 3 به بعد منسوخ اعلام شده‌است. نحوه صدا زدن on بجای دلیگیت به شکل زیر خواهد بود:
$("#area").on('click','.test',function(e){...});


نکته مهم : بعضی‌ها برای راحتی کار بدین شکل کار میکنند ولی این شیوه فرقی با متد live  ندارد.
$("body").on('click','.test',function(e){...});

در حالت Bubbling up این گونه است که اگر کدی به شکل زیر باشد و رویداد کلیک روی text هدف ما باشد، رویداد کلیک به سمت اجداد آن حرکت میکند. یعنی ابتدا رویداد کلیک b اجرا میشود، سپس a و سپس رویداد کلیک div اجرا میشود و الی آخر:
<div> <a> <b>text</b> </a> </div>
برای حل این مسئله و جلوگیری از این اتفاق میتوان از متد stopPropagation استفاده کرد که در حالت استفاده از متد on جواب میدهد؛ ولی در متد live، استفاده از آن بی فایده است. کد زیر را میتوانید با حالت‌های مختلف بررسی کرده و نتیجه این متد را در کنسول مرورگر خود ببینید:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <script
  src="https://code.jquery.com/jquery-1.12.4.min.js"
  integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
  crossorigin="anonymous"></script>
        <script src="http://code.jquery.com/jquery-migrate-1.4.1.js"></script>
    <script>
    $(document).ready(function(){
      $(".myspan").on( "click",".test", function(e) {
        e.stopPropagation();
        console.log('test fired!') } );
      $(".myspan").on( "click", function() { console.log(' myspan fired!') } );
      $(".mydiv").on( "click", function() { console.log(' mydiv fired!') } );

    });
    </script>
  </head>
  <body>
<div class="mydiv">
  <span class="myspan">
    <button type="button" class="test">Ok</button>
  </span>

</div>
  </body>
</html>

نکته تکمیلی
اینکه در استفاده از دلیگیت و on میتوان رویدادها را به شکل زیر هم مورد استفاده قرار داد:
$().on({
    'click': function (e) {
       // function
    },
    'hover': function (e) {
       // function    
    }
});
مطالب
چطور مسیریابی‌های ASP.NET MVC را دیباگ کنیم؟
سؤال: من برای تهیه sitemap برنامه، یک route سفارشی نوشته‌ام تا یک فایل xml ایی را که در وب سرور، وجود خارجی ندارد، در آدرس‌های سایت قابل دسترسی کند. برای مثال:
            routes.MapRoute(
                "SiteMap_route", // Route name
                "sitemap.xml", // URL with parameters
                new { controller = "Sitemap", action = "index", name = UrlParameter.Optional, area = "" } // Parameter defaults
            );
با استفاده از این مسیریابی خاص، قرار است هر زمانیکه آدرس http://site/sitemap.xml در مرورگر وارد شد، برنامه در پشت صحنه، به صورت خودکار به کنترلر sitemap و اکشن متد index آن مراجعه کرده و یک محتوای پویای XML ایی را تولید کند و بازگشت دهد. اما ... کار نمی‌کند! یعنی آدرس یاد شده اصلا پاسخ نمی‌دهد. چرا؟ نحوه‌ی ثبت مسیریابی سفارشی تعریف شده نیز به صورت زیر است:
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

            routes.MapRoute(
                "SiteMap_route", // Route name
                "sitemap.xml", // URL with parameters
                new { controller = "Sitemap", action = "index", name = UrlParameter.Optional, area = "" } // Parameter defaults
            );
        }
پاسخ: اگر با تقدم و تاخر و معنای مسیریابی‌های تعریف شده آشنایی داشته باشید، شاید بلافاصله بتوانید مشکل را حدس بزنید. اما اگر تعداد مسیریابی‌های سفارشی تعریف شده زیاد باشد، اینکار ساده نیست و حتما نیاز به ابزار دیباگ دارد تا بتوان تشخیص داد که در صفحه جاری کدامیک از مسیریابی‌های تعریف شده کار را تمام کرده‌اند و نوبت به دیگری نرسیده است.

برای این منظور می‌توان از افزونه‌ای به نام RouteDebug نوشته یکی از اعضای سابق تیم ASP.NET MVC استفاده کرد:
کار کردن با آن نیز بسیار ساده است.
الف) ارجاعی را به اسمبلی RouteDebug.dll (حاصل از کامپایل پروژه فوق) به پروژه جاری ASP.NET MVC خود اضافه کنید.
ب) سپس به فایل Global.asax.cs خود مراجعه و در سطر آخر متد Application_Start آن، فراخوانی ذیل را اضافه نمائید:
 RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
اکنون هر صفحه و آدرسی را که باز کنید، بجای محتوای اصلی صفحه، مسیریابی‌های فعال و برنده آن‌را مشاهده خواهید کرد. برای مثال در صفحه اول برنامه داریم:


نکته مهمی که در این تصویر باید به آن دقت داشت، اولین True سبز رنگی است که نمایش می‌دهد. یعنی اولین مسیریابی که کار هدایت و نمایش صفحه جاری را برعهده دارد. در اجرای عادی ASP.NET MVC، همینجا کار پردازش سیستم مسیریابی صفحه جاری خاتمه خواهد یافت و نوبت به سایرین نخواهد رسید.
در مورد صفحه sitemap.xml چطور؟ اگر این آدرس را در مرورگر، بدون فعال سازی افزونه RouteDebug وارد کنیم، پیام 404 را دریافت می‌کنیم. اگر افزونه را فعال کنیم، اینبار به صفحه زیر خواهیم رسید:


بله. همانطور که مشاهده می‌کنید، مسیریابی پیش فرض، اینبار نیز برنده بوده است و اولین تطابق صورت گرفته با آن صورت می‌گیرد. بنابراین اصلا کار به استفاده از مسیریابی سفارشی تعریف شده توسط ما نخواهد رسید.
بنابراین محل تعریف این مسیریابی را اکنون به پیش از مسیریابی پیش فرض انتقال می‌دهیم:
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "SiteMap_route", // Route name
                "sitemap.xml", // URL with parameters
                new { controller = "Sitemap", action = "index", name = UrlParameter.Optional, area = "" } // Parameter defaults
            );

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );      
        }
در ادامه اگر مجددا مسیر sitemap.xml را درخواست کنیم، به تصویر ذیل خواهیم رسید:


بله. با این تنظیم صورت گرفته، اینبار دیگر سیستم مسیریابی، برای تفسیر مسیر سفارشی تعریف شده، به سراغ مسیریابی پیش فرض نخواهد رفت و کار همینجا خاتمه می‌یابد.

سؤال: آیا اینکار تداخلی در عملکرد اصلی برنامه ایجاد نمی‌کند؟ مثلا اگر به مسیر index کنترلر home مراجعه کنیم، مشکلی نخواهد بود؟
پاسخ: خیر. برای آزمایش آن باز هم به افزونه RouteDebug مراجعه خواهیم کرد:


همانطور که مشخص است، مسیریابی برنده در این حالت، همان مسیریابی پیش فرض است و نه مسیریابی سفارشی آدرس خاص sitemap.xml سایت.


یک نکته تکمیلی
افزونه گلیمپس نیز امکان دیباگ Routeها را دارد؛ اما توانایی بررسی مشکلات Routing یک خطای 404 مانند مثال فوق را حداقل تا زمان نگارش این مطلب ندارد و همان افزونه RouteDebug یاد شده، بهتر عمل می‌کند.
مطالب
استفاده از خاصیت Local در Entity Framework
زمانی که از LINQ To Entity  استفاده می‌کنیم، با هر بار اجرای یک کوئری، این کوئری به سمت دیتابیس ارسال شده و اطلاعات مورد نظر را بازیابی می‌کند. حال اگر ما موجودیت جدیدی را به Context جاری اضافه کرده ولی آن را ذخیره نکرده باشیم، به علت عدم وجود موجودیت در دیتابیس (در حافظه وجود دارد) کوئری ارسالی ما این موجودیت جدید را شامل نمی‌شود. البته شایان ذکر است زمانیکه از متد Find استفاده می‌کنیم، به صورت پیش فرض ابتدا داخل حافظه کاوش شده و در صورت عدم وجود اطلاعات، کوئری را در دیتابیس اجرا می‌کند.
نکته قابل توجه این است که بعنوان مثال ما نیاز داریم یک لیست از موجودیت‌ها را به اشکال زیر داشته باشیم.
  1. به صورت لیست
  2. به صورت لیست sort شده براساس Name
  3. فیلتر بر روی لیستی از فیلدهای موجود
  4. این  لیست باید شامل تمامی داده‌های موجود (چه در رم و چه در دیتابیس) باشد.
نکته: توسط متد ToList میتوان به لیستی از موجودیت‌های مورد نظر دست یافت ولی امکان استفاده از تمامی داده‌های موجود (چه در رم و چه در دیتابیس) میسر نمی‌باشد.
کلاس DbSet خاصیتی به نام Local دارد که امکان استفاده از  تمامی داده‌های موجود را به ما می‌دهد و شامل هر داده‌ای که از دیتابیس Load شده، هر داده‌ای که اضافه شده، هر داده‌ای  که پاک شده (Delete Flag) ولی هنوز ذخیره نشده می‌شود. بنابراین در هنگام استفاده باید توجه داشت به علت اینکه هیچ نوع کوئری به دیتابیس ارسال نشده، قطعه کد زیر دارای مقدار Destinations in memory: 0 خواهد بود
    private static void GetLocalDestinationCount()
    {
        using (var context = new BreakAwayContext())
        {
            var count = context.Destinations.Local.Count;
            Console.WriteLine("Destinations in memory: {0}", count);
        }
    }

استفاده از متد Load
برای مثال می‌توانیم از Foreach استفاده کنیم و تمام اطلاعات مورد نظر را بدست آوریم
    private static void GetLocalDestinationCount()
    {
        using (var context = new BreakAwayContext())
        {
            foreach (var destination in context.Destinations)
            {
                Console.WriteLine(destination.Name);
            }
            var count = context.Destinations.Local.Count;
            Console.WriteLine("Destinations in memory: {0}", count);
        }
    }
کد بالا یک حلقه بر روی موجودیت‌های Destinations است که نیازی به توضیح خاصی ندارد.
حال با استفاده از متد Load قادر به جمع آوری اطلاعات دیتابیس به داخل رم نیز خواهیم بود و کد بالا تمیزتر خواهد شد.
    private static void GetLocalDestinationCountWithLoad()
    {
        using (var context = new BreakAwayContext())
        {
            context.Destinations.Load();
            var count = context.Destinations.Local.Count;
            Console.WriteLine("Destinations in memory: {0}", count);
        }
    }
متد Load یک extension method روی IQueryable<T> است که در فضای نام System.Data.Entity موجود است. پس امکان اجرای یک  LINQ query و سپس Load کردن آن را در حافظه را خواهیم داشت.
به کد زیر توجه کنید:
    private static void LoadAustralianDestinations()
    {
        using (var context = new BreakAwayContext())
        {
            var query = from d in context.Destinations
                        where d.Country == "Australia"
                        select d;
            query.Load();
            var count = context.Destinations.Local.Count;
            Console.WriteLine("Aussie destinations in memory: {0}", count);
        }
    }
همچنین ما قادر به استفاده از  LINQ query روی داده‌های Local که این متد در حافظه جمع آوری کرده، نیز خواهیم بود. 
به کد زیر توجه کنید.
    private static void LocalLinqQueries()
    {
        using (var context = new BreakAwayContext())
        {
            context.Destinations.Load();
            var sortedDestinations = from d in context.Destinations.Local
                                     orderby d.Name
                                     select d;
            Console.WriteLine("All Destinations:");
            foreach (var destination in sortedDestinations)
            {
                Console.WriteLine(destination.Name);

            }
        }
        var aussieDestinations = from d in context.Destinations.Local
                                 where d.Country == "Australia"
                                 select d;
        Console.WriteLine();
        Console.WriteLine("Australian Destinations:");
        foreach (var destination in aussieDestinations)
        {
            Console.WriteLine(destination.Name);
        }
    }
ابتدا کلیه داده‌ها Load می‌شود سپس به وسیله Foreach نام‌ها استخراج می‌شوند. سپس ار همان داده‌ها جهت اعمال فیلتر، استفاده مشود.

تفاوت بین Linq provider‌های مختلف:

عموماً دیتابیسها حساس به حروف کوچک و بزرگ نیستند؛ به عنوان مثال اگر Great و great در دیتابیس وجود داشته باشند اگر به دیتابیس کوئری اسال شود و درخواست great  داشته باشد هر دو را شامل میشود. حال اگر از Local استفاده شود به جهت اینکه در واقع از Linq to Object استفاده می‌کند فقط great را شامل خواهد شد.
تفاوت دیگر این است که LINQ to Object از متد Last پشتیبانی می‌کند ولی LINQ to Entities خیر.
در پست بعدی قصد دارم در مورد ObservableCollection توضیحاتی کلی بدهم.
مطالب
آشنایی با CLR: قسمت هفتم
کدهای IL و تایید آن ها

ساختار استکی
IL از ساختار استک استفاده می‌کند. به این معنی که تمامی دستور العمل‌ها داخل آن push شده و نتیجه‌ی اجرای آن‌ها pop می‌شوند. از آنجا که IL به طور مستقیم ارتباطی با ثبات‌ها ندارد، ایجاد زبانهای برنامه نویسی جدید بر اساس CLR بسیار راحت‌تر هست و عمل کامپایل، تبدیل کردن به کدهای IL می‌باشد.

بدون نوع بودن(Typeless)
از دیگر مزیت‌های آن این است که کدهای IL بدون نوع هستند. به این معنی که موقع افزودن دستورالعملی به داخل استک، دو عملگر وارد می‌شوند و هیچ جداسازی در رابطه با سیستم‌های 32 یا 64 بیت صورت نمی‌گیرد و موقع اجرای برنامه است که تصمیم می‌گیرد از چه عملگرهایی باید استفاده شود.

Virtual Address Space
بزرگترین مزیت این سیستم‌ها امنیت و مقاومت آن هاست. موقعی که تبدیل کد IL به سمت کد بومی صورت می‌گیرد، CLR فرآیندی را با نام verification یا تاییدیه، اجرا می‌کند. این فرآیند تمامی کدهای IL را بررسی می‌کند تا از امنیت کدها اطمینان کسب کند. برای مثال بررسی می‌کند که هر متدی صدا زده می‌شود با تعدادی پارامترهای صحیح صدا زده شود و به هر پارامتر آن نوع صحیحش پاس شود و مقدار بازگشتی هر متد به درستی استفاده شود. متادیتا شامل اطلاعات تمامی پیاده سازی‌ها و متدها و نوع هاست که در انجام تاییدیه مورد استفاده قرار می‌گیرد.
در ویندوز هر پروسه، یک آدرس مجازی در حافظه دارد و این جدا سازی حافظه و ایجاد یک حافظه مجازی کاری لازم اجراست. شما نمی‌توانید به کد یک برنامه اعتماد داشته باشید که از حد خود تخطی نخواهد کرد و فرآیند برنامه‌ی دیگر را مختل نخواهد کرد. با خواندن و نوشتن در یک آدرس نامعتبر حافظه، ما این اطمینان را کسب می‌کنیم که هیچ گاه تخطی در حافظه صورت نمی‌گیرد.
قبلا به طور مفصل در این مورد ذخیره سازی در حافظه صحبت کرده ایم.

Hosting
از آنجا که پروسه‌های ویندوزی به مقدار زیادی از منابع سیستم عامل نیاز دارند که باعث کاهش منابع و محدودیت در آن می‌شوند و نهایت کارآیی سیستم را پایین می‌آورد، ولی با کاهش تعدادی برنامه‌های در حال اجرا به یک پروسه‌ی واحد می‌توان کارآیی سیستم را بهبود بخشید و منابع کمتری مورد استفاده قرار می‌گیرند که این یکی دیگر از مزایای کدهای managed نسبت به unmanaged است. CLR در حقیقت این قابلیت را به شما می‌دهد تا چند برنامه‌ی مدیریت شده را در قالب یک پروسه به اجرا درآورید. هر برنامه‌ی مدیریت شده به طور پیش فرض بر روی یک appDomain اجرا می‌گردد و هر فایل EXE روی حافظه‌ی مجازی مختص خودش اجرا می‌شود. هر چند پروسه‌هایی از قبیل IIS و SQL Server که پروسه‌های CLR را پشتیبانی یا هاست می‌کنند می‌توانند تصمیم بگیرند که آیا appDomain‌ها را در یک پروسه‌ی واحد اجرا کنند یا خیر که در مقاله‌های آتی آن را بررسی می‌کنیم.

کد ناامن یا غیر ایمن UnSafe Code
به طور پیش فرض سی شارپ کدهای ایمنی را تولید می‌کند، ولی این اجازه را می‌دهد که اگر برنامه نویس بخواهد  کدهای ناامن بزند، قادر به انجام آن باشد. این کدهای ناامن دسترسی مستقیم به خانه‌های حافظه و دستکاری بایت هاست. این مورد قابلیت قدرتمندی است که به توسعه دهنده اجازه می‌دهد که با کدهای مدیریت نشده ارتباط برقرار کند یا یک الگوریتم با اهمیت زمانی بالا را جهت بهبود کارآیی، اجرا کند.
 هر چند یک کد ناامن سبب ریسک بزرگی می‌شود و می‌تواند وضعیت بسیاری از ساختارهای ذخیره شده در حافظه را به هم بزند و امنیت برنامه را تا حد زیادی کاهش دهد.  به همین دلیل سی شارپ نیاز دارد تا تمامی متدهایی که شامل کد unsafe هستند را با کلمه کلیدی unsafe علامت گذاری کند. همچنین کمپایلر سی شارپ نیاز دارد تا شما این کدها را با سوئیچ unsafe/ کامپایل کنید.

موقعیکه جیت تلاش دارد تا یک کد ناامن را کامپایل کند، اسمبلی را بررسی می‌کند که آیا این متد اجازه و تاییدیه آن را دارد یا خیر. آیا  System.Security.Permissions.SecurityPermission با فلگ SkipVerification مقدار دهی شده است یا خیر. اگر پاسخ مثبت بود JIT آن‌ها را کامپایل کرده و اجازه‌ی اجرای آن‌ها را می‌دهد. CLR به این کد اعتماد می‌کند و امیدوار است که آدرس دهی مستقیم و دستکاری بایت‌های حافظه موجب آسیبی نگردد. ولی اگر پاسخ منفی بود، یک استثناء از نوع System.InvalidProgramException یا System.Security.VerificationException را ایجاد می‌کند تا از اجرای این متد جلوگیری به عمل آید. در واقع کل برنامه خاتمه میابد ولی آسیبی به حافظه نمی‌زند.

پی نوشت: سیستم به  اسمبلی هایی که از روی ماشین یا از طریق شبکه  به اشتراک گذاشته می‌شوند اعتماد کامل میکند که این اعتماد شامل کدهای ناامن هم می‌شود ولی به طور پیش فرض به اسمبلی هایی از طریق اینترنت اجرا می‌شوند اجازه اجرای کدهای ناامن را نمی‌دهد و اگر شامل کدهای ناامن شود یکی از خطاهایی که در بالا به آن اشاره کردیم را صادر می‌کنند. در صورتی که مدیر یا کاربر سیستم اجازه اجرای آن را بدهد تمامی مسئولیت‌های این اجرا بر گردن اوست.

در این زمینه مایکروسافت ابزار سودمندی را با نام PEVerify .exe را معرفی کرده است که به بررسی تمامی متدهای یک اسمبلی پرداخته و در صورت وجود کد ناامن به شما اطلاع میدهد. بهتر است از این موضوع اطلاع داشته باشید که این ابزار نیاز دارد تا به متادیتاهای یک اسمبلی نیاز داشته باشید. باید این ابزار بتواند به تمامی ارجاعات آن دسترسی داشته باشد که در مورد عملیات بایندینگ در آینده بیشتر صحبت می‌کنیم.

IL و حقوق حق تالیف آن
بسیاری از توسعه دهندگان از اینکه IL هیچ شرایطی برای حفظ حق تالیف آن‌ها ایجاد نکرده است، ناراحت هستند. چرا که ابزارهای زیادی هستند که با انجام عملیات مهندسی معکوس می‌توانند به الگوریتم آنان دست پیدا کنند و میدانید که IL خیلی سطح پایین نیست و برگرداندن آن به شکل یک کد، کار راحت‌تری هست و بعضی ابزارها کدهای خوبی هم ارائه می‌کنند. از دست این ابزارها می‌توان به ILDisassembler و  JustDecompile اشاره کرد.
اگر علاقمند هستید این عیب را برطرف کنید، می‌توانید از ابزارهای ثالث که به ابزارهای obfuscator (یک نمونه سورس باز ) معروف هستند استفاده کنید تا با کمی پیچیدگی در متادیتاها، این مشکل را تا حدی برطرف کنند. ولی این ابزارها خیلی کامل نیستند، چرا که نباید به کامپایل کردن کار لطمه بزنند. پس اگر باز خیلی نگران این مورد هستید می‌توانید الگوریتم‌های حساس و اساسی خود را در قالب unmanaged code ارائه کنید که در بالا اشاراتی به آن کرده‌ایم.
برنامه‌های تحت وب به دلیل عدم دسترسی دیگران از امنیت کاملتری برخوردار هستند.
مطالب
مدیریت تغییرات در سیستم های مبتنی بر WCF
تشریح مسئله : در صورتی که بعد از انتشار برنامه؛ در نسخه بعدی مدل سمت سرور تغییر کرده باشد و امکان بروز رسانی مدل‌های سمت کلاینت وجود نداشته باشد برای حل این مسئله بهترین روش کدام است.
نکته : برای فهم بهتر مطالب آشنایی اولیه با مفاهیم WCF الزامی است.
ابتدا مدل زیر را در نظر بگیرید:
   [DataContract]
    public class Book 
    {
        [DataMember]
        public int Code { get; set; }

        [DataMember]
        public string Name { get; set; }             
    }
حالا یک سرویس برای دریافت و ارسال اطلاعات این مدل به کلاینت می‌نویسیم.
  [ServiceContract]
    public interface ISampleService
    {
        [OperationContract]
        IEnumerable<Book> GetAll();

        [OperationContract]
        void Save( Book book );
    }
و سرویسی که Contract بالا رو پیاده سازی کند.
public class SampleService : ISampleService
    {
        public List<Book> ListOfBook 
        {
            get; 
            private set; 
        }

        public SampleService()
        {
            ListOfBook = new List<Book>();
        }
        public IEnumerable<Book> GetAll()
        {
            ListOfBook.AddRange( new Book[] 
            {
                new Book(){Code=1 , Name="Book1"},
                new Book(){Code=2 , Name="Book2"},
            } );
            return ListOfBook;
        }

        public void Save( Book book )
        {
            ListOfBook.Add( book );
        }
    }
 متد GetAll برای ارسال اطلاعات به کلاینت و متد Save نیز برای دریافت اطلاعات از کلاینت.
حالا یک پروژه Console Application بسازید و از روش AddServiceReference سرویس مورد نظر را به Client اضافه کنید. برنامه را تست کنید. بدون هیچ مشکلی کار می‌کند.
حالا اگر در نسخه بعدی سیستم مجبور شویم به مدل Book یک خاصیت دیگر به نام Author را نیز اضافه کنیم و امکان Update کردن سرویس در سمت کلاینت وجود نداشته باشد چه اتفاقی خواهد افتاد.
به صورت زیر:
 [DataContract]
    public class Book 
    {
        [DataMember]
        public int Code { get; set; }
        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public string Author { get; set; }
    }
به طور پیش فرض اگر در DataContract‌های سمت سرور و کلاینت اختلاف وجود داشته باشد این موارد نادیده گرفته می‌شوند. یعنی همیشه مقدار خاصیت Author برابر null خواهد بود.
نکته : برای Value Type‌ها مقادیر پیش فرض و برای Reference Type‌ها مقدار Null.
اگر برای DataMemberAttribute خاصیت IsRequired را برابر true کنیم از این پس برای هر درخواستی که مقدار Author  آن مقدار نداشته باشد یک Protocol Exception  پرتاب می‌شود. به صورت زیر:
[DataMember( IsRequired = true )]
public string Author { get; set; }
اما این همیشه راه حل مناسبی نیست.
روش دیگر این است که Desrialize کردن مدل را تغییر دهیم. بدین معنی که هر گاه مقدار Author برابر Null بود یک مقدار پیش فرض برای آن در نظر بگیریم. این کار با نوشتن یک متد و قراردادن OnDeserializingAttribute به راحتی امکان پذیر است. کلاس Book به صورت زیر تغییر می‌کند.
  [DataContract]
    public class Book
    {
        [DataMember]
        public int Code { get; set; }
        [DataMember]
        public string Name { get; set; }

        [DataMember( IsRequired = true )]
        public string Author { get; set; }

        [OnDeserializing]
        private void OnDeserializing( StreamingContext context )
        {
            if ( string.IsNullOrEmpty( Author ) )
            {
                Author = "Masoud Pakdel";
            }
        }
    }
حال اگر از سمت کلاینت کلاس Book دریافت شود که مقدار خاصیت Author آن برابر Null باشد توسط متد OnDeserializing مقدار پیش فرض به آن اعمال می‌شود.مثل تصویر زیر:

روش بعدی استفاده از اینترفیس IExtensibleDataObject  است. بعد از اینکه کلاس Book این اینترفیس را پیاده سازی کرد مشکل Versioning Round Trip حل می‌شود. به این صورت که سرویس یا کلاینتی که نسخه قدیمی را می‌شناسد اگر نسخه جدید را دریافت کند خصوصیاتی را که نمی‌شناسد مثل Author در خاصیت ExtensionData ذخیره می‌شود و هنگامی که کلاس Book برای سرویس یا کلاینتی که نسخه جدید را می‌شناسد DataContractSerializer اطلاعات مورد نظر را از خصوصیت ExtensionData بیرون می‌کشد و کلاس Book جدید را باز سازی می‌کند. بررسی کلاس ExtensionData توسط خود DataContractSreializer انجام می‌شود و نیاز به هیچ گونه ای کد نویسی ندارد.

[DataContract]
    public class Book : IExtensibleDataObject
    {
        [DataMember]
        public int Code { get; set; }
        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public string Author { get; set; }
    
        public virtual ExtensionDataObject ExtensionData
        {
            get { return _extensionData; }
            set
            {
                _extensionData = value;
            }
        }
        private ExtensionDataObject _extensionData;
    }
اگر کد متد GetAll سمت سرور را به صورت زیر تغییر دهیم که خاصیت Author هم مقدار داشته باشد با استفاده از خاصیت ExtensionData کلاینت هم از این مقدار مطلع خواهد شد.
public IEnumerable<Book> GetAll()
        {
            ListOfBook.AddRange( new Book[] 
            {
                new Book(){Code=1 , Name="Book1", Author="Masoud Pakdel"},
                new Book(){Code=2 , Name="Book2" },
            } );
            return ListOfBook;
        }
کلاینت هم به صورت زیر :

همان طور که می‌بینید این نسخه از کلاینت هیچ گونه اطلاعی از وجود یک خاصیت به نام Author ندارد ولی از طریق ExtensionData متوجه می‌شود یک خاصیت به نام Author به مدل سمت سرور اضافه شده است.

اما در صورتی که قصد داشته باشیم که یک سرویس خاص از همان نسخه قدیمی کلاس Book استفاده کند و نیاز به نسخه جدید آن نداشته باشد می‌توانیم این کار را از طریق مقدار دهی True به خاصیت IgnoreExtensionDataObject  در ServiceBehaviorAttribute انجام داد. بدین شکل

 [ServiceBehavior( IgnoreExtensionDataObject = true )]
  public class SampleService : ISampleService
از این پس سرویس بالا از همان مدل Book بدون خاصیت Author استفاده می‌کند.

منابع :
مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 6 - سرویس‌ها و تزریق وابستگی‌ها
پیشنیازها (الزامی)

«بررسی مفاهیم معکوس سازی وابستگی‌ها و ابزارهای مرتبط با آن»
«اصول طراحی SOLID»
«مطالعه‌ی بیشتر»


تزریق وابستگی‌ها (یا Dependency injection = DI) به معنای ارسال نمونه‌ای/وهله‌ای از وابستگی (یک سرویس) به شیء وابسته‌ی به آن (یک کلاینت) است. در فرآیند تزریق وابستگی‌ها، یک کلاس، وهله‌های کلاس‌های دیگر مورد نیاز خودش را بجای وهله سازی مستقیم، از یک تزریق کننده دریافت می‌کند. بنابراین بجای نوشتن newها در کلاس جاری، آن‌ها را به صورت وابستگی‌هایی در سازنده‌ی کلاس تعریف می‌کنیم تا توسط یک IoC Container تامین شوند. در اینجا به فریم ورک‌هایی که کار وهله سازی این وابستگی‌ها را انجام می‌دهند، IoC Container و یا DI container می‌گوییم (IoC =  inversion of control ).
چندین نوع تزریق وابستگی‌ها وجود دارند که دو حالت زیر، عمومی‌ترین آن‌ها است:
الف) تزریق در سازنده‌ی کلاس: لیست وابستگی‌های یک کلاس، به عنوان پارامترهای سازنده‌ی آن ذکر می‌شوند.
ب) تزریق در خواص یا Setter injection: کلاینت خواصی get و set را به صورت public معرفی می‌کند و سپس IoC Container با وهله سازی آن‌ها، وابستگی‌های مورد نیاز را تامین خواهد کرد.


تزریق وابستگی‌ها در ASP.NET Core

برخلاف نگارش‌های قبلی ASP.NET، این نگارش جدید از ابتدا با دید پشتیبانی کامل از DI طراحی شده‌است و این مفهوم، در سراسر اجزای آن به صورت یکپارچه‌ای پشتیبانی می‌شود. همچنین به همراه یک minimalistic DI container توکار نیز هست .
این IoC Container توکار از 4 حالت طول عمر ذیل پشتیبانی می‌کند:
- instance: در هربار نیاز به یک وابستگی خاص، تنها یک وهله از آن در اختیار مصرف کننده قرار می‌گیرد و در اینجا شما هستید که مسئول تعریف نحوه‌ی وهله سازی این شیء خواهید بود (برای بار اول).
- transient: هربار که نیاز به وابستگی خاصی بود، یک وهله‌ی جدید از آن توسط IoC Container تولید و ارائه می‌شود.
- singleton: در این حالت تنها یک وهله از وابستگی درخواست شده در طول عمر برنامه تامین می‌شود.
- scoped: در طول عمر یک scope خاص، تنها یک وهله از وابستگی درخواست شده، در اختیار مصرف کننده‌ها قرار می‌گیرد. برای مثال مرسوم است که به ازای یک درخواست وب، تنها یک وهله از شیء‌ایی خاص در اختیار تمام مصرف کننده‌های آن قرار گیرد (single instance per web request).

طول عمر singleton، برای سرویس‌ها و کلاس‌های config مناسب هستند. به این ترتیب به کارآیی بالاتری خواهیم رسید و دیگر نیازی نخواهد بود تا هر بار این اطلاعات خوانده شوند. حالت scoped برای وهله سازی الگوی واحد کار و پیاده سازی تراکنش‌ها مناسب است. برای مثال در طی یک درخواست وب، یک تراکنش باید صورت گیرد.
حالت scoped در حقیقت نوع خاصی از حالت transient است. در حالت transient صرفنظر از هر حالتی، هربار که وابستگی ویژه‌ای درخواست شود، یک وهله‌ی جدید از آن تولید خواهد شد. اما در حالت scoped فقط یک وهله‌ی از وابستگی مورد نظر، در بین تمام اشیاء وابسته‌ی به آن، در طول عمر آن scope تولید می‌شود.
بنابراین در برنامه‌های وب دو نوع singleton برای معرفی کلاس‌های config و نوع scoped برای پیاده سازی تراکنش‌ها و همچنین بالابردن کارآیی برنامه در طی یک درخواست وب (با عدم وهله سازی بیش از اندازه‌ی از کلاس‌های مختلف مورد نیاز)، بیشتر از همه به کار برده می‌شوند.


یک مثال کاربردی: بررسی نحوه‌ی تزریق یک سرویس سفارشی به کمک IoC Container توکار ASP.NET Core


مثال جاری که بر اساس ASP.NET Core Web Application و با قالب خالی آن ایجاد شده‌است، دارای نام فرضی Core1RtmEmptyTest است. در همین پروژه بر روی پوشه‌ی src، کلیک راست کرده و گزینه‌ی Add new project را انتخاب کنید و سپس یک پروژه‌ی جدید از نوع NET Core -> Class library. را به آن، با نام Core1RtmEmptyTest.Services اضافه کنید (تصویر فوق).
در ادامه کلاس نمونه‌ی سرویس پیام‌ها را به همراه اینترفیس آن، با محتوای زیر به آن اضافه کنید:
namespace Core1RtmEmptyTest.Services
{
    public interface IMessagesService
    {
        string GetSiteName();
    }
 
    public class MessagesService : IMessagesService
    {
        public string GetSiteName()
        {
            return "DNT";
        }
    }
}
در ادامه به پروژه‌ی Core1RtmEmptyTest مراجعه کرده و بر روی گره references آن کلیک راست کنید. در اینجا گزینه‌ی add reference را انتخاب کرده و سپس Core1RtmEmptyTest.Services را انتخاب کنید، تا اسمبلی آن‌را بتوان در پروژه‌ی جاری استفاده کرد.


انجام اینکار معادل است با افزودن یک سطر ذیل به فایل project.json پروژه:
{
    "dependencies": {
        // same as before
        "Core1RtmEmptyTest.Services": "1.0.0-*"
    },
در ادامه قصد داریم این سرویس را به متد Configure کلاس Startup تزریق کرده و سپس خروجی رشته‌ای آن‌را توسط میان افزار Run آن نمایش دهیم. برای این منظور فایل Startup.cs را گشوده و امضای متد Configure را به نحو ذیل تغییر دهید:
public void Configure(
    IApplicationBuilder app,
    IHostingEnvironment env,
    IMessagesService messagesService)
همانطور که در قسمت قبل نیز عنوان شد، متد Configure دارای امضای ثابتی نیست و هر تعداد سرویسی را که نیاز است، می‌توان در اینجا اضافه کرد. یک سری از سرویس‌ها مانند IApplicationBuilder و IHostingEnvironment پیشتر توسط IoC Container توکار ASP.NET Core معرفی و ثبت شده‌اند. به همین جهت، همینقدر که در اینجا ذکر شوند، کار می‌کنند و نیازی به تنظیمات اضافه‌تری ندارند. اما سرویس IMessagesService ما هنوز به این IoC Container معرفی نشده‌است. بنابراین نمی‌داند که چگونه باید این اینترفیس را وهله سازی کند.
public void Configure(
    IApplicationBuilder app,
    IHostingEnvironment env,
    IMessagesService messagesService)
{ 
    app.Run(async context =>
    {
        var siteName = messagesService.GetSiteName();
        await context.Response.WriteAsync($"Hello {siteName}");
    });
}
در این حالت اگر برنامه را اجرا کنیم، به این خطا برخواهیم خورد:
 System.InvalidOperationException
No service for type 'Core1RtmEmptyTest.Services.IMessagesService' has been registered.
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.Invoke(object instance, IApplicationBuilder builder)

System.Exception
Could not resolve a service of type 'Core1RtmEmptyTest.Services.IMessagesService' for the parameter 'messagesService' of method 'Configure' on type 'Core1RtmEmptyTest.Startup'.
at Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.Invoke(object instance, IApplicationBuilder builder)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
برای رفع این مشکل، به متد ConfigureServices کلاس Startup مراجعه کرده و سیم کشی‌های مرتبط را انجام می‌دهیم. در اینجا باید اعلام کنیم که «هر زمانیکه به IMessagesService رسیدی، یک وهله‌ی جدید (transient) از کلاس MessagesService را به صورت خودکار تولید کن و سپس در اختیار مصرف کننده قرار بده»:
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IMessagesService, MessagesService>();
    }
در اینجا نحوه‌ی ثبت یک سرویس را در IoC Containser توکار ASP.NET Core ملاحظه می‌کنید. تمام حالت‌های طول عمری که در ابتدای بحث عنوان شدند، یک متد ویژه‌ی خاص خود را در اینجا دارند. برای مثال حالت transient دارای متد ویژه‌ی AddTransient است و همینطور برای سایر حالت‌ها. این متدها به صورت جنریک تعریف شده‌اند و آرگومان اول آن‌ها، اینترفیس سرویس و آرگومان دوم، پیاده سازی آن‌ها است (سیم کشی اینترفیس، به کلاس پیاده سازی کننده‌ی آن).

پس از اینکار، مجددا برنامه را اجرا کنید. اکنون این خروجی باید مشاهده شود:


و به این معنا است که اکنون IoC Cotanier توکار ASP.NET Core، می‌داند زمانیکه به IMessagesService رسید، چگونه باید آن‌را وهله سازی کند.


چه سرویس‌هایی به صورت پیش فرض در IoC Container توکار ASP.NET Core ثبت شده‌اند؟

در ابتدای متد ConfigureServices یک break point را قرار داده و برنامه را در حالت دیباگ اجرا کنید:


همانطور که ملاحظه می‌کنید، به صورت پیش فرض 16 سرویس در اینجا ثبت شده‌اند که تاکنون با دو مورد از آن‌ها کار کرده‌ایم.


امکان تزریق وابستگی‌ها در همه جا!

در مثال فوق، سرویس سفارشی خود را در متد Configure کلاس آغازین برنامه تزریق کردیم. نکته‌ی مهم اینجا است که برخلاف نگارش‌های قبلی ASP.NET MVC (یعنی بدون نیاز به تنظیمات خاصی برای قسمت‌های مختلف برنامه)، می‌توان این تزریق‌ها را در کنترلرها، در میان افزارها، در فیلترها در ... همه جا و تمام اجزای ASP.NET Core 1.0 انجام داد و دیگر اینبار نیازی نیست تا نکته‌ی ویژه‌ی نحوه‌ی تزریق وابستگی‌ها در فیلترها یا کنترلرهای ASP.NET MVC را یافته و سپس اعمال کنید. تمام این‌ها از روز اول کار می‌کنند. همینقدر که کار ثبت سرویس خود را در متد ConfigureServices انجام دادید، این سرویس در سراسر اکوسیستم ASP.NET Core، قابل دسترسی است.


نیاز به تعویض IoC Container توکار ASP.NET Core

قابلیت تزریق وابستگی‌های توکار ASP.NET Core صرفا جهت برآورده کردن نیازمندی‌های اصلی آن طراحی شده‌است و نه بیشتر. بنابراین توسط آن قابلیت‌های پیشرفته‌ای را که سایر IoC Containers ارائه می‌دهند، نخواهید یافت. برای مثال تعویض امکانات تزریق وابستگی‌های توکار ASP.NET Core با StructureMap این مزایا را به همراه خواهد داشت:
 • امکان ایجاد child/nested containers (پشتیبانی از سناریوهای چند مستاجری)
 • پشتیبانی از Setter Injection
 • امکان انتخاب سازنده‌ای خاص (اگر چندین سازنده تعریف شده باشند)
 • سیم کشی خودکار یا Conventional "Auto" Registration (برای مثال اتصال اینترفیس IName به کلاس Name به صورت خودکار و کاهش تعداد تعاریف ابتدای برنامه)
 • پشتیبانی توکار از Lazy و Func
 • امکان وهله سازی از نوع‌های concrete (یا همان کلاس‌های معمولی)
 • پشتیبانی از مفاهیمی مانند Interception و AOP
 • امکان اسکن اسمبلی‌های مختلف جهت یافتن اینترفیس‌ها و اتصال خودکار آن‌ها (طراحی‌های افزونه پذیر)


روش تعویض IoC Container توکار ASP.NET Core با StructureMap

جزئیات این جایگزین کردن را در مطلب «جایگزین کردن StructureMap با سیستم توکار تزریق وابستگی‌ها در ASP.NET Core 1.0» می‌توانید مطالعه کنید.
یا می‌توانید از روش فوق استفاده کنید و یا اکنون قسمتی از پروژه‌ی رسمی استراکچرمپ در آدرس https://github.com/structuremap/structuremap.dnx جهت کار با NET Core. طراحی شده‌است. برای کار با آن نیاز است این مراحل طی شوند:
الف) دریافت بسته‌ی نیوگت StructureMap.Dnx
برای این منظور بر روی گره references کلیک راست کرده و گزینه‌ی manage nuget packages را انتخاب کنید. سپس در برگه‌ی browse آن، StructureMap.Dnx را جستجو کرده و نصب نمائید (تیک مربوط به انتخاب pre releases هم باید انتخاب شده باشد):


انجام این مراحل معادل هستند با افزودن یک سطر ذیل به فایل project.json برنامه:
{
    "dependencies": {
        // same as before  
        "StructureMap.Dnx": "0.5.1-rc2-final"
    },
ب) جایگزین کردن Container استراکچرمپ با Container توکار ASP.NET Core
پس از نصب بسته‌ی StructureMap.Dnx، به کلاس آغازین برنامه مراجعه کرده و این تغییرات را اعمال کنید:
public class Startup
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddDirectoryBrowser();
 
        var container = new Container();
        container.Configure(config =>
        {
            config.Scan(_ =>
            {
                _.AssemblyContainingType<IMessagesService>();
                _.WithDefaultConventions();
            });
            //config.For<IMessagesService>().Use<MessagesService>();
 
            config.Populate(services);
        });
        container.Populate(services);
 
        return container.GetInstance<IServiceProvider>();
    }
در اینجا ابتدا خروجی متد ConfigureServices، به IServiceProvider تغییر کرده‌است تا استراکچرمپ این تامین کننده‌ی سرویس‌ها را ارائه دهد. سپس Container مربوط به استراکچرمپ، وهله سازی شده و همانند روال متداول آن، یک سرویس و کلاس پیاده سازی کننده‌ی آن معرفی شده‌اند (و یا هر تنظیم دیگری را که لازم بود باید در اینجا اضافه کنید). در پایان کار متد Configure آن و پس از این متد، نیاز است متدهای Populate فراخوانی شوند (اولی تعاریف را اضافه می‌کند و دومی کار تنظیمات را نهایی خواهد کرد).
سپس وهله‌ای از IServiceProvider، توسط استراکچرمپ تامین شده و بازگشت داده می‌شود تا بجای IoC Container توکار ASP.NET Core استفاده شود.
در این مثال چون در متد Scan، کار بررسی اسمبلی لایه سرویس برنامه با قراردادهای پیش فرض استراکچرمپ انجام شده‌است، دیگر نیازی به سطر تعریف config.For نیست. در اینجا هرگاه IName ایی یافت شد، به کلاس Name متصل می‌شود (name هر نامی می‌تواند باشد).