[asp.net-mvc] أين تضع AutoMapper.CreateMaps؟



Answers

يمكنك فعلاً وضعها في أي مكان طالما أن مشروعك على الويب يشير إلى التجميع الذي هو فيه. في وضعك أضعه في طبقة الخدمة حيث يمكن الوصول إليه بواسطة طبقة الويب وطبقة الخدمة وفي وقت لاحق إذا قررت قم بتنفيذ تطبيق وحدة التحكم أو كنت تقوم بعمل مشروع اختبار وحدة ، وستكون تكوين الخرائط متاحًا من تلك المشاريع أيضًا.

في Global.asax ستقوم بالاتصال بالطريقة التي تقوم بتعيين جميع خرائطك. انظر أدناه:

ملف AutoMapperBootStrapper.cs

public static class AutoMapperBootStrapper
{
     public static void BootStrap()
     {  
         AutoMapper.CreateMap<Object1, Object2>();
         // So on...


     }
}

Global.asax على بدء التطبيق

اتصل وحسب

AutoMapperBootStrapper.BootStrap();

الآن قد يجادل بعض الناس ضد هذه الطريقة ينتهك بعض المبادئ الصلبة ، والتي لديهم حجج صحيحة. هنا هم للقراءة.

تكوين Automapper في Bootstrapper ينتهك مبدأ مفتوح مغلق؟

Question

أنا أستخدم AutoMapper في ASP.NET MVC . قيل لي أنه يجب أن نقل AutoMapper.CreateMap أي مكان آخر لأن لديهم الكثير من النفقات العامة. لست متأكدًا من كيفية تصميم التطبيق الخاص بي لوضع هذه المكالمات في مكان واحد فقط.

لدي طبقة ويب وطبقة خدمة وطبقة بيانات. كل مشروع من تلقاء نفسها. أنا استخدم Ninject ل DI كل شيء. AutoMapper في كل من طبقات الويب والخدمة.

إذن ما هو إعداد برنامج AutoMapper الخاص ببرنامج CreateMap؟ أين وضعه؟ كيف يمكنك أن نسميها؟




بالنسبة لأولئك الذين (ضائع) باستخدام:

  • WebAPI 2
  • SimpleInjector 3.1
  • AutoMapper 4.2.1 (مع الملفات الشخصية)

وإليك كيفية إدارة دمج AutoMapper في " https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API ". أيضا ، شكر كبير لهذه الإجابة (والسؤال)

1 - إنشاء مجلد في مشروع WebAPI يسمى "ProfileMappers". في هذا المجلد أضع جميع فئات ملفات التعريف الخاصة بي والتي تقوم بإنشاء التعيينات الخاصة بي:

public class EntityToViewModelProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<User, UserViewModel>();
    }

    public override string ProfileName
    {
        get
        {
            return this.GetType().Name;
        }
    }
}

2 - في App_Start الخاص بي ، لدي SimpleInjectorApiInitializer الذي يقوم بتكوين حاوية SimpleInjector الخاصة بي:

public static Container Initialize(HttpConfiguration httpConfig)
{
    var container = new Container();

    container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

    //Register Installers
    Register(container);

    container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

    //Verify container
    container.Verify();

    //Set SimpleInjector as the Dependency Resolver for the API
    GlobalConfiguration.Configuration.DependencyResolver =
       new SimpleInjectorWebApiDependencyResolver(container);

    httpConfig.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

    return container;
}

private static void Register(Container container)
{
     container.Register<ISingleton, Singleton>(Lifestyle.Singleton);

    //Get all my Profiles from the assembly (in my case was the webapi)
    var profiles =  from t in typeof(SimpleInjectorApiInitializer).Assembly.GetTypes()
                    where typeof(Profile).IsAssignableFrom(t)
                    select (Profile)Activator.CreateInstance(t);

    //add all profiles found to the MapperConfiguration
    var config = new MapperConfiguration(cfg =>
    {
        foreach (var profile in profiles)
        {
            cfg.AddProfile(profile);
        }
    });

    //Register IMapper instance in the container.
    container.Register<IMapper>(() => config.CreateMapper(container.GetInstance));

    //If you need the config for LinqProjections, inject also the config
    //container.RegisterSingleton<MapperConfiguration>(config);
}

3 - Startup.cs

//Just call the Initialize method on the SimpleInjector class above
var container = SimpleInjectorApiInitializer.Initialize(configuration);

4 - ثم ، في وحدة التحكم الخاصة بك فقط حقن كما عادة واجهة IMAPER:

private readonly IMapper mapper;

public AccountController( IMapper mapper)
{
    this.mapper = mapper;
}

//Using..
var userEntity = mapper.Map<UserViewModel, User>(entity);



بالإضافة إلى أفضل إجابة ، هناك طريقة جيدة تستخدم Autofac IoC liberary لإضافة بعض الأتمتة. مع هذا يمكنك فقط تعريف ملفات التعريف الخاصة بك بغض النظر عن المبتدئين.

   public static class MapperConfig
    {
        internal static void Configure()
        {

            var myAssembly = Assembly.GetExecutingAssembly();

            var builder = new ContainerBuilder();

            builder.RegisterAssemblyTypes(myAssembly)
                .Where(t => t.IsSubclassOf(typeof(Profile))).As<Profile>();

            var container = builder.Build();

            using (var scope = container.BeginLifetimeScope())
            {
                var profiles = container.Resolve<IEnumerable<Profile>>();

                foreach (var profile in profiles)
                {
                    Mapper.Initialize(cfg =>
                    {
                        cfg.AddProfile(profile);
                    });                    
                }

            }

        }
    }

واستدعاء هذا السطر في أسلوب Application_Start :

MapperConfig.Configure();

يعرض الرمز أعلاه جميع الطبقات الفرعية للملفات الشخصية وابدأ تشغيلها تلقائيًا.




من إصدار جديد من AutoMapper باستخدام أسلوب ثابت تم إهمال Mapper.Map (). لذلك يمكنك إضافة MapperConfiguration كخاصية ثابتة إلى MvcApplication (Global.asax.cs) واستخدامها لإنشاء مثيل من مخطط.

App_Start

public class MapperConfig
{
    public static MapperConfiguration MapperConfiguration()
    {
        return new MapperConfiguration(_ =>
        {
            _.AddProfile(new FileProfile());
            _.AddProfile(new ChartProfile());
        });
    }
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    internal static MapperConfiguration MapperConfiguration { get; private set; }

    protected void Application_Start()
    {
        MapperConfiguration = MapperConfig.MapperConfiguration();
        ...
    }
}

BaseController.cs

    public class BaseController : Controller
    {
        //
        // GET: /Base/
        private IMapper _mapper = null;
        protected IMapper Mapper
        {
            get
            {
                if (_mapper == null) _mapper = MvcApplication.MapperConfiguration.CreateMapper();
                return _mapper;
            }
        }
    }

https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API




لأولئك منكم الذين التقيد بما يلي:

  1. باستخدام حاوية ioc
  2. لا تحب كسر مفتوحة لهذا الغرض
  3. لا يعجبك ملف تهيئة أحادي

لقد قمت بعمل تحويلة بين الملفات الشخصية والاستفادة من حاوية ioc الخاصة بي:

تكوين IoC:

public class Automapper : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly().BasedOn<Profile>().WithServiceBase());

        container.Register(Component.For<IMappingEngine>().UsingFactoryMethod(k =>
        {
            Profile[] profiles = k.ResolveAll<Profile>();

            Mapper.Initialize(cfg =>
            {
                foreach (var profile in profiles)
                {
                    cfg.AddProfile(profile);
                }
            });

            profiles.ForEach(k.ReleaseComponent);

            return Mapper.Engine;
        }));
    }
}

مثال التكوين:

public class TagStatusViewModelMappings : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<Service.Contracts.TagStatusViewModel, TagStatusViewModel>();
    }
}

مثال على الاستخدام:

public class TagStatusController : ApiController
{
    private readonly IFooService _service;
    private readonly IMappingEngine _mapper;

    public TagStatusController(IFooService service, IMappingEngine mapper)
    {
        _service = service;
        _mapper = mapper;
    }

    [Route("")]
    public HttpResponseMessage Get()
    {
        var response = _service.GetTagStatus();

        return Request.CreateResponse(HttpStatusCode.Accepted, _mapper.Map<List<ViewModels.TagStatusViewModel>>(response)); 
    }
}

المقايضة هي أنه عليك الرجوع إلى مخطط بواسطة واجهة IMappingEngine بدلا من مخطط ثابت ، ولكن هذا هو الاتفاقية التي يمكنني العيش معها.




Related