حین کار با ASP.NET Identity به اینترفیسی به نام IIdentityMessageService شبیه به اینترفیس ذیل میرسیم:
فرض کنید از آن دو پیاده سازی در برنامه برای ارسال پیامها توسط ایمیل و همچنین توسط SMS، وجود دارد:
اکنون کلاس مدیریت کاربران برنامه، در سازندهی خود نیاز به دو وهله، از این سرویسهای متفاوت، اما در اصل مشتق شدهی از یک اینترفیس دارد:
در این حالت صرف تنظیمات ابتدایی انتساب یک اینترفیس، به یک کلاس مشخص کافی نیست:
از این جهت که در سازندهی کلاس UsersManagerService دقیقا مشخص نیست، پارامتر اول باید سرویس SMS باشد یا ایمیل؟
برای حل این مشکل میتوان به نحو ذیل عمل کرد:
در اینجا توسط متد Ctor که مخفف Constructor یا سازندهی کلاس است، مشخص میکنیم که اگر به پارامتر smsService رسیدی، از کلاس SmsService استفاده کن و در مورد کلاس سرویس ایمیل نیز به همین ترتیب. اینبار اگر برنامه را اجرا کنیم:
همانطور که در تصویر مشخص است، هر کدام از پارامترها، توسط کلاسهای متفاوتی مقدار دهی شدهاند؛ هرچند از یک اینترفیس مشخص استفاده میکنند.
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید:
Dependency-Injection-Samples/DI09
namespace SameInterfaceDifferentClasses.Services.Contracts { public interface IMessageService { void Send(string message); } }
public class EmailService : IMessageService { public void Send(string message) { // ... } } public class SmsService : IMessageService { public void Send(string message) { //todo: ... } }
public interface IUsersManagerService { void ValidateUserByEmail(int id); } public class UsersManagerService : IUsersManagerService { private readonly IMessageService _emailService; private readonly IMessageService _smsService; public UsersManagerService(IMessageService emailService, IMessageService smsService) { _emailService = emailService; _smsService = smsService; } public void ValidateUserByEmail(int id) { _emailService.Send("Validated."); } }
ioc.For<IMessageService>().Use<SmsService>(); ioc.For<IMessageService>().Use<EmailService>();
برای حل این مشکل میتوان به نحو ذیل عمل کرد:
public static class SmObjectFactory { private static readonly Lazy<Container> _containerBuilder = new Lazy<Container>(defaultContainer, LazyThreadSafetyMode.ExecutionAndPublication); public static IContainer Container { get { return _containerBuilder.Value; } } private static Container defaultContainer() { return new Container(ioc => { // map same interface to different concrete classes ioc.For<IMessageService>().Use<SmsService>(); ioc.For<IMessageService>().Use<EmailService>(); ioc.For<IUsersManagerService>().Use<UsersManagerService>() .Ctor<IMessageService>("smsService").Is<SmsService>() .Ctor<IMessageService>("emailService").Is<EmailService>(); }); } }
var usersManagerService = SmObjectFactory.Container.GetInstance<IUsersManagerService>(); usersManagerService.ValidateUserByEmail(id: 1);
همانطور که در تصویر مشخص است، هر کدام از پارامترها، توسط کلاسهای متفاوتی مقدار دهی شدهاند؛ هرچند از یک اینترفیس مشخص استفاده میکنند.
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید:
Dependency-Injection-Samples/DI09