Complicated Mapping Question

43 views
Skip to first unread message

george.w...@gmail.com

unread,
Apr 16, 2015, 9:47:36 AM4/16/15
to automapp...@googlegroups.com
Here are my classes

interface ITrackCreatedDateTime
{
        DateTime CreatedDateTime { get; set; }
}

interface ITrackUpdatedDateTime
{
        DateTime UpdatedDateTime { get; set; }
}

interface ITrackedModel : ITrackCreatedDateTime, ITrackUpdatedDateTime
{
        int? CreatedByUserID { get; set; }
        int? UpdatedByUserID { get; set; }
}

//I have about 25 classes / interfaces that look like this
interface SampleTrackedModel : ITrackedModel
{
}

//Then I have about 25 that looks like this
interface SampleUpdatedModel : ITrackCreatedDateTime, ITrackUpdatedDateTime
{
}


I am looking for a generic way to map the inherited interfaces without having to add them to every map

can this be done?




Jimmy Bogard

unread,
Apr 16, 2015, 11:07:50 AM4/16/15
to automapper-users
What does your mapping configuration look like today?

--
You received this message because you are subscribed to the Google Groups "AutoMapper-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to automapper-use...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

george.w...@gmail.com

unread,
Apr 16, 2015, 11:12:13 AM4/16/15
to automapp...@googlegroups.com, george.w...@gmail.com
abstract class CommonProfile : Profile
    {
        protected abstract IORMEngine Database { get; }
        

        protected TDestination Create<TDestination>(ResolutionContext context)
        {
            return Database.Tables.Create<TDestination>();
        }

        private void ToDataModel<TViewModel, TDataModel>(IMappingExpression<TViewModel, TDataModel> action)
        {

        }

        private void ToViewModel<TViewModel, TDataModel>(IMappingExpression<TDataModel, TViewModel> action)
        {

        }

        protected void ConfigureMap<TViewModel, TDataModel>(
                Action<IMappingExpression<TViewModel, TDataModel>> toDataModel = null,
                Action<IMappingExpression<TDataModel, TViewModel>> toViewModel = null
            )
        {
            if (toDataModel == null) { toDataModel = ToDataModel; }
            if (toViewModel == null) { toViewModel = ToViewModel; }

            if (typeof(TDataModel).IsInterface && Database.Tables.Contains(typeof(TDataModel)))
            {                
                IDataModelDescriptor desc = Database.Tables.Describe<TDataModel>();
                toDataModel(CreateMap<TViewModel, TDataModel>().ConstructUsing((o) => Create<TDataModel>(o)));                
            }else
            {
                toDataModel(CreateMap<TViewModel, TDataModel>());
            }

            toViewModel( CreateMap<TDataModel, TViewModel>() );
 

        }

        private void ToDataModelNull<TViewModel, TDataModel>(IMappingExpression<TViewModel, TDataModel> action) where TViewModel : IModel
        {

        }

        private void ToViewModelNull<TViewModel, TDataModel>(IMappingExpression<TDataModel, TViewModel> action) where TViewModel : IModel
        {

        }


        private void ToViewRecordNull<TDataModel, TViewModel>(IMappingExpression<TDataModel, TViewModel> action) where TViewModel : Record
        {

        }

        private IMappingExpression<TDataModel, Record> RecordMap<TDataModel>(IDataModelDescriptor desc)
        {
            IMappingExpression<TDataModel, Tracking> trackingMap = CreateMap<TDataModel, Tracking>();

            #region Tracking Mapping
            if (desc.Fields.ContainsField("CreatedByUserID"))
            { trackingMap.ForMember(dest => dest.CreatedByUserID, opt => opt.MapFrom(o => desc.Fields["CreatedByUserID"].GetValue(o))); }
            else 
            { trackingMap.ForMember(dest => dest.CreatedByUserID, opt => opt.Ignore()); }

            if (desc.Fields.ContainsField("UpdatedByUserID"))
            { trackingMap.ForMember(dest => dest.UpdatedByUserID, opt => opt.MapFrom(o => desc.Fields["UpdatedByUserID"].GetValue(o))); }
            else
            { trackingMap.ForMember(dest => dest.UpdatedByUserID, opt => opt.Ignore()); }

            if (desc.Fields.ContainsField("CreatedDateTime"))
            { trackingMap.ForMember(dest => dest.CreatedDateTime, opt => opt.MapFrom(o => desc.Fields["CreatedDateTime"].GetValue(o))); }
            else
            { trackingMap.ForMember(dest => dest.CreatedDateTime, opt => opt.Ignore()); }

            if (desc.Fields.ContainsField("UpdatedDateTime"))
            { trackingMap.ForMember(dest => dest.UpdatedDateTime, opt => opt.MapFrom(o => desc.Fields["UpdatedDateTime"].GetValue(o))); }
            else
            { trackingMap.ForMember(dest => dest.UpdatedDateTime, opt => opt.Ignore()); }
            #endregion

            IMappingExpression<TDataModel, Record> recordMap =
              CreateMap<TDataModel, Record>()
                  .ForMember(dest => dest.Identifier, opt => opt.MapFrom(o => CommonConverter.MapIdentifier(Database.Tables.Describe<TDataModel>(), o)))
                  .ForMember(dest => dest.Tracking, opt => opt.MapFrom(o => CommonConverter.Map<TDataModel, Tracking>(o)))
              ;


            #region Record Map
            if (desc.Fields.ContainsField("Name"))
            { recordMap.ForMember(dest => dest.Name, opt => opt.MapFrom(o => desc.Fields["Name"].GetValue(o))); }
            else
            { recordMap.ForMember(dest => dest.Name, opt => opt.Ignore()); }

            if (desc.Fields.ContainsField("Description"))
            { recordMap.ForMember(dest => dest.Description, opt => opt.MapFrom(o => desc.Fields["Description"].GetValue(o))); }
            else
            { recordMap.ForMember(dest => dest.Description, opt => opt.Ignore()); }
            #endregion

            return recordMap;
        }


        protected void Configure<TViewModel, TDataModel>(Expression<Func<TDataModel, object>> primaryKey,
            Action<IMappingExpression<TViewModel, TDataModel>> toDataModel = null, 
            Action<IMappingExpression<TDataModel, TViewModel>> toViewModel = null,
            Action<IMappingExpression<TDataModel, Record>> toViewRecord = null
            ) where TViewModel : Model
        {
            IDataModelDescriptor desc = Database.Tables.Describe<TDataModel>();

            if (toDataModel == null) { toDataModel = ToDataModelNull; }
            if (toViewModel == null) { toViewModel = ToViewModelNull; }
            if (toViewRecord == null) { toViewRecord = ToViewRecordNull; }


            IMappingExpression<TDataModel, Record> recordMap = RecordMap<TDataModel>(desc);

            toViewRecord(recordMap);
            

            //, PDQ.Framework.ORM.ITrackUpdatedDateTime
            IMappingExpression<TViewModel, TDataModel> to =
                CreateMap<TViewModel, TDataModel>()
                        .ForMember(primaryKey, opt => opt.Ignore())
                        .ConstructUsing((o) => Create<TDataModel>(o))
                        .AfterMap((source, dest) => { if (source.Identifier.ID.HasValue) { desc.KeyFields[0].SetValue(dest, source.Identifier.ID.Value); } })
                ;

            bool tf = false;
            if (tf)
            {
                if (desc.Fields.ContainsField("CreatedByUserID"))
                { to.ForMember("CreatedByUserID", opt => opt.Ignore()); }

                if (desc.Fields.ContainsField("UpdatedByUserID"))
                { to.ForMember("UpdatedByUserID", opt => opt.Ignore()); }

                if (desc.Fields.ContainsField("CreatedDateTime"))
                { to.ForMember("CreatedDateTime", opt => opt.Ignore()); }

                if (desc.Fields.ContainsField("UpdatedDateTime"))
                { to.ForMember("UpdatedDateTime", opt => opt.Ignore()); }
            }

            IMappingExpression<TDataModel, TViewModel> from =
                CreateMap<TDataModel, TViewModel>()
                    .ForMember(dest => dest.Identifier, opt => opt.MapFrom(o => CommonConverter.MapIdentifier(Database.Tables.Describe<TDataModel>(), o)))
                    .ForMember(dest => dest.Tracking, opt => opt.MapFrom(o => CommonConverter.Map<TDataModel,Tracking>(o)))
                ;


            if (typeof(IExternalModel).IsAssignableFrom(typeof(TViewModel)) && typeof(IExternallySynchronizable).IsAssignableFrom(typeof(TDataModel)))
            {
                //Mapper.Map<TDataModel, TViewModel>(dataModel, viewModel)
                //to.ForMember("External", opt => opt.MapFrom(o => Mapper.Map<ExternalReference>(o)));
                to.AfterMap((viewModel, dataModel) => ToModel<IExternalModel, IExternallySynchronizable>(viewModel as IExternalModel, dataModel as IExternallySynchronizable));
                from.AfterMap((dataModel, viewModel) => ToView<IExternallySynchronizable, IExternalModel>(dataModel as IExternallySynchronizable, viewModel as IExternalModel));
            }

            toDataModel(to);
            toViewModel(from);
 
        }

        //private void ToViewRecordNull<TDataModel, TViewModel>(IMappingExpression<TDataModel, TViewModel> action) where TViewModel : Record

        private void ToView<TDataModel, TViewModel>(TDataModel model, TViewModel view)
            where TDataModel : IExternallySynchronizable
            where TViewModel : IExternalModel
        {
            if (model == null || view == null) { return; }
            view.External = new ExternalReference();
            view.External.Locator = model.ExternalLocator;
            view.External.Identifier = model.ExternalIdentifier;
        }

        private void ToModel<TViewModel, TDataModel>(TViewModel view, TDataModel model)
            where TViewModel : IExternalModel
            where TDataModel : IExternallySynchronizable
        {
            if (model == null || view == null) { return; }
            if (view.External == null) { return; }

            model.ExternalIdentifier = view.External.Identifier;
            model.ExternalLocator = view.External.Locator;
        }



        protected IMappingExpression<TDataModel, TViewModel> ReadOnly<TDataModel, TViewModel>() where TViewModel : IModel
        {
            IDataModelDescriptor desc = Database.Tables.Describe<TDataModel>();

            #region TDataModel --> Record
            IMappingExpression<TDataModel, Record> recordMap =
                CreateMap<TDataModel, Record>().
                    ForMember(dest => dest.Identifier, opt => opt.MapFrom(o => CommonConverter.MapIdentifier(Database.Tables.Describe<TDataModel>(), o)))
                ;

            if (desc.Fields.ContainsField("Name"))
            {
                recordMap.
                    ForMember(dest => dest.Name, opt => opt.MapFrom(o => desc.Fields["Name"].GetValue(o)))
                ;
            }

            if (desc.Fields.ContainsField("Description"))
            {
                recordMap.
                    ForMember(dest => dest.Description, opt => opt.MapFrom(o => desc.Fields["Description"].GetValue(o)))
                ;
            }
            #endregion


            IMappingExpression<TDataModel, TViewModel> map =
                CreateMap<TDataModel, TViewModel>()
                    .ForMember(dest => dest.Identifier, opt => opt.MapFrom(o => CommonConverter.MapIdentifier(Database.Tables.Describe<TDataModel>(), o)))
                    .ForMember(dest => dest.Tracking, opt => opt.MapFrom(o => CommonConverter.Map<TDataModel, Tracking>(o)))
                ;

            if (typeof(IExternalModel).IsAssignableFrom(typeof(TViewModel)) && typeof(IExternallySynchronizable).IsAssignableFrom(typeof(TDataModel)))
            {
                map.AfterMap((dataModel, viewModel) => ToView<IExternallySynchronizable, IExternalModel>(dataModel as IExternallySynchronizable, viewModel as IExternalModel));
            }

            return map;
        }
    }
}






    class AccountMappingProfile : CommonProfile
    {
        protected override IORMEngine Database { get { return Databases.Registry; } }

        protected override void Configure()
        {
            Configure<StrategicPartner, StrategicPartnerRecord>(o => o.StrategicPartnerID,
                    toDataModel => { },
                    toViewModel => { toViewModel.ForMember(dest => dest.Resellers, opt => opt.Ignore()); }
                );
            Configure<Reseller, ResellerRecord>(o => o.ResellerID,
                    toDataModel => { },
                    toViewModel => { toViewModel.ForMember(dest => dest.StrategicPartners, opt => opt.Ignore()); }
                );


            Configure<TechnologyLicensee, TechnologyLicenseeRecord>(o => o.TechnologyLicenseeID,
                    toDataModel =>
                    {
                        toDataModel
                            .ForMember(dest => dest.ApplicationNetworkID, opt => opt.Ignore())
                            .ForMember(dest => dest.DatabaseShardID, opt => opt.Ignore())
                            ;
                    },
                    toViewModel => { }
                );
        }
    }
}

Jimmy Bogard

unread,
Apr 24, 2015, 11:19:57 AM4/24/15
to automapper-users
So today - no, BUT this is one of the use cases I'm looking at for AutoMapper 4. Can you open up a GH issue for your use case?

George Westwater

unread,
Apr 26, 2015, 9:45:39 AM4/26/15
to automapp...@googlegroups.com
ok I will do that 

--
You received this message because you are subscribed to a topic in the Google Groups "AutoMapper-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/automapper-users/HJ_12C-aLhA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to automapper-use...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
George Westwater
technomystic
(913) 712-9458
Reply all
Reply to author
Forward
0 new messages