Mapping with a condition - c#

I want to map 2 objects based on a condition, if true mapp else ignore, the condition is not a part of source neither destination
var mapperconfig = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Source, Destination>()
.ForMember(source => source.Titulaires,
opt => opt.Condition(titulaires.HasValue && titulaires == true));
....
});
the extension method Condition() accepts just a type related to source or destination.

AutoMapper allows you to add conditions to properties that must be met before that property will be mapped.
Eg.
public class Foo
{
public int baz;
}
public class Bar
{
public uint baz;
}
public class Program
{
public static void Main()
{
Mapper.CreateMap<Foo,Bar>().ForMember(dest => dest.baz, opt => opt.Condition(src => (src.baz >= 0)));
var foo1 = new Foo { baz=-1 };
var bar1 = Mapper.Map<Bar>(foo1);
Console.WriteLine("bar1.baz={0}", bar1.baz);
var foo2 = new Foo{ baz=100 };
var bar2 = Mapper.Map<Bar>(foo2);
Console.WriteLine("bar2.baz={0}", bar2.baz);
}
}
Also, they give Preconditions functionality
See this link Conditional Mapping

thank you all for your help, I find a way to test my conditions into my automapper configuration : MapperConfiguration mappConf = new MapperConfiguration(config => {
config.CreateMap()
.ForMember(destination => destination.member, option => option.Condition(item => _condition == true))........});

Related

Autofac - get all instances of classes whose interface implements specific interface [duplicate]

Consider the following
builder.Register(c => new A());
builder.Register(c => new B());
builder.Register(c => new C());
B and C are both ISomeInterface.
I would now like to get an IEnumerable of all registered objects that implement ISomeInterface.
How can I accomplish this in Autofac?
Just tried this, works and does not depend on lifetime context:
Enumerate types using Activator instead
var types = con.ComponentRegistry.Registrations
.Where(r => typeof(ISomeInterface).IsAssignableFrom(r.Activator.LimitType))
.Select(r => r.Activator.LimitType);
Then to resolve:
IEnumerable<ISomeInterface> lst = types.Select(t => con.Resolve(t) as ISomeInterface);
If you have
container.Register(c => new A()).As<ISomeInterface>();
container.Register(c => new B()).As<ISomeInterface>();
Then when you do
var classes = container.Resolve<IEnumerable<ISomeInterface>>();
You will get a variable that is a list of ISomeInterface, containing A and B
Here is how I did it.
var l = Container.ComponentRegistry.Registrations
.SelectMany(x => x.Services)
.OfType<IServiceWithType>()
.Where(x =>
x.ServiceType.GetInterface(typeof(ISomeInterface).Name) != null)
.Select(c => (ISomeInterface) c.ServiceType);
I was looking for a similar solution for registrations done as follows:
builder.RegisterType<Bamboo>().As<IExoticTree>();
// and/or
builder.RegisterType<SolidOak>().Keyed<IMountainTree>(key);
where IExoticTree and IMountainTree inherit from a common ITree interface.
With those, the service type (e.g. registered interface) is different from the LimitType and hence, the proposed solution is not applicable.
I got inspired by the accepted solution to manage these as well with the following code:
IEnumerable<ITree> instances = scope.ComponentRegistry.Registrations
.Where(r => typeof(ITree).IsAssignableFrom(r.Activator.LimitType))
.Select(r => r.Services.First())
.Select(s => scope.ResolveService(s) as ITree)
.Distinct();
Hope it helps someone ^^
I needed to resolve based on some context. So slight variation...
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(ISomeStrategy)))
.Where(t => typeof(ISomeStrategy).IsAssignableFrom(t))
.AsSelf();
builder.Register<Func<SomeEnum, ISomeStrategy>>(c =>
{
var types = c.ComponentRegistry.Registrations
.Where(r => typeof(ISomeStrategy).IsAssignableFrom(r.Activator.LimitType))
.Select(r => r.Activator.LimitType);
ISomeStrategy[] lst = types.Select(t => c.Resolve(t) as ISomeStrategy).ToArray();
return (someEnum) =>
{
return lst.FirstOrDefault(x => x.CanProcess(someEnum));
};
});
Then for your class using the strategy
public SomeProvider(Func<SomeType, ISomeStrategy> someFactory)
{
_someFactory = someFactory;
}
public void DoSomething(SomeType someType)
{
var strategy = _someFactory(someType);
strategy.DoIt();
}
Clarification for any one searching this with regards to Inherited Class
Ex :
public static IEnumerable<Type> GetTypesInherit<T>(this Assembly assembly)
{
var types = assembly.GetTypes()
.Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(T)))
.ToList();
return types;
}
Installer :
public static IContainer Install()
{
var builder = new ContainerBuilder();
var executingAssembly = Assembly.GetExecutingAssembly();
var testScreens = executingAssembly.GetTypesInherit<TestScreen>();
foreach (var testScreen in testScreens)
{
builder.RegisterType(testScreen).As<TestScreen>();
}
var container = builder.Build();
return container;
}
Usage (Implicit) :
public class MainViewModel(IEnumerable<TestScreen> testScreens)
{}

Pass property getter to linq expression function

I'm trying to take a method and make it generic, and I'm a little stuck because the method uses Linq to look at elements. Here's the example method:
private List<int> GetListFromIDS(string ids, IEnumerable<SubSpace_Function> data)
{
if (string.IsNullOrEmpty(ids))
return null;
var list = ids
.Split(new char[] { ',' })
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => int.Parse(x.Trim()));
return data
.Where(x => list.Contains(x.Function_Id)))
.Select(x => x.Function_Id)
.ToList();
}
The parts that change are the type (SubSpace_Function) and the property to lookup Function_ID.
I know I can just change the SubSpace_Function part to T in the generic method signature, but since each type will have it's own property to lookup, I'm not sure how to 'pass' in something like Function_Id.
It's pretty easy to do with Func:
private List<int> GetListFromIDS<T>(string ids, IEnumerable<T> data, Func<T, IEnumerable<int>, bool> filterExpression, Func<T, int> selectExpression)
{
if (string.IsNullOrEmpty(ids))
return null;
var list = ids
.Split(',') // simplify
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => int.Parse(x.Trim()));
return data
.Where(x => filterExpression(x, list))
.Select(selectExpression)
.ToList();
}
And call using:
var data = GetListFromIDS<SubSpace_Function>(
"123,123,123",
someList,
(x, list) => list.Contains(x.Function_Id),
x => x.Function_Id);
Another way is to call the select Func inline:
private List<int> GetListFromIDS<T>(string ids, IEnumerable<T> data, Func<T, int> selectExpression)
{
if (string.IsNullOrEmpty(ids))
return null;
var list = ids
.Split(',') // simplify
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => int.Parse(x.Trim()));
return data
.Where(x => list.Contains(selectExpression(x)))
.Select(selectExpression)
.ToList();
}
And call using:
var data = GetListFromIDS<SubSpace_Function>(
"123,123,123",
someList,
x => x.Function_Id);
I know this focused on generics, but I took the approach of using an interface instead:
interface ISubSpaceFunction
{
int FunctionId { get; }
}
class Foo : ISubSpaceFunction
{
public int FunctionId => FooMethodForFunctionId();
private int FooMethodForFunctionId()
{
//do foo function id stuff
throw new NotImplementedException();//so it compiles
}
}
class Bar : ISubSpaceFunction
{
public int FunctionId => BarMethodForFunctionId();
private int BarMethodForFunctionId()
{
//do bar function id stuff
throw new NotImplementedException();//so it compiles
}
}
static class MyClass
{
private static List<int> GetListFromIds(string idsString, IEnumerable<ISubSpaceFunction> subSpaceFunctions)
{
var ids = string.IsNullOrWhiteSpace(idsString) ?
Enumerable.Empty<int>() :
idsString.Split(new[] { ',' })
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x.Trim())
.Select(int.Parse);
var idSet = new HashSet<int>(ids);
return subSpaceFunctions.Select(ssf => ssf.FunctionId)
.Where(ids.Contains)
.ToList();
}
}
class Example
{
public void Test()
{
string ids = "1, 2, 3, 4, 5";
var subSpaceFunctions = new ISubSpaceFunction[] { new Foo(), new Bar() };
var results = MyClass.GetListFromIds(ids, subSpaceFunctions);
}
}
My attitude on this and related matters is that the code to get the Property value for each particular type has to go somewhere, so it might as well go in the Type's class. This ensures that if the Property's value is needed elsewhere, there is no duplication. This also allows for mixing multiple types that satisfy ISubSpaceFunction, as is done in the example, and you could easily have the interface also specify some common method to be used elsewhere.
I also prefer returning empty collections over null when writing these kinds of LINQ based transformation methods in order to minimize null checking "down the pipeline," but a "fail fast" use case may call for a null return value.

How do I append a Property into an MOQ Object at Runtime

I am hoping to create a property dynamically at run-time so the Setup can use THAT PROPERTY for its data and/or database value(s):
QUESTION:
How can I append a property to the MOCK INSTANCE dynamically?
EXAMPLE:
public Mock<IRepository<tClaims>> MockClaimsRepository()
{
var repository = new Mock<IRepository<tClaims>>();
// HOW DO I DO THIS?
repository.SetupProperty<Claim>(//* How do I append a dynamic property here *//)
repository.SetupProperty<List<Claims>>(//* How do I append a dynamic property here *//)
repository.Setup(x => x.GetActive()).Returns(repository.Claims.AsQueryable());
repository.Setup(x => x.GetAll()).Returns(repository.Claims.AsQueryable());
repository.Setup(x => x.GetById(repository.Claim.Claim_ID)).Returns(Claim);
repository.Setup(x => x.Find(new object[] { It.IsAny<object>() })).Returns(repository.Claim);
repository.Setup(x => x.Add(repository.Claim)).Verifiable();
repository.Setup(x => x.AddRange(repository.Claims)).Verifiable();
repository.Setup(x => x.Update(repository.Claim)).Verifiable();
repository.Setup(x => x.Delete(repository.Claim)).Verifiable();
repository.Setup(x => x.Delete(It.IsAny<object>())).Verifiable();
return repository;
}
You can't directly add new properties to the mocked object, what you can do is add an implementation of another interface using As<> method with the properties you want.
But if your goal is use this properties to give logic and state to the mock, then you can use variables for that, something like this:
public Mock<IRepository<Claims>> MockClaimsRepository()
{
var repository = new Mock<IRepository<Claims>>();
var claims = new List<Claims>(); // Add variables to be used in the setups
repository.Setup(x => x.GetAll()).Returns(claims.AsQueryable());
repository.Setup(x => x.GetById(It.IsAny<int>())).Returns<int>(id => claims.Find(c => c.Id == id));
repository.Setup(x => x.Add(It.IsAny<Claims>())).Callback<Claims>(c => claims.Add(c));
repository.Setup(x => x.Delete(It.IsAny<Claims>())).Callback<Claims>(c => claims.Remove(c));
...
return repository;
}
These variables will not be disposed when yo return from MockClaimsRepository since you are referencing it in the setups.
You can use SetupAllProperties() ?
Specifies that the all properties on the mock should have "property behavior",
meaning that setting its value will cause it to be saved and
later returned when the property is requested. (this is also
known as "stubbing"). The default value for each property will be the
one generated as specified by the property for the mock.
Just to update Arturo to be generic like your repository:
public Mock<IRepository<T>> MockRepository<T, TKey>() where T : BaseEntity<TKey> //(for Id )
{
var repository = new Mock<IRepository<T>>();
var entities = new List<T>(); // Add variables to be used in the setups
repository.Setup(x => x.GetAll()).Returns(entities.AsQueryable());
repository.Setup(x => x.GetById(It.IsAny<TKey>())).Returns<TKey>(id => entities.Find(c => c.Id == id));
repository.Setup(x => x.Add(It.IsAny<T>())).Callback<T>(c => entities.Add(c));
repository.Setup(x => x.Delete(It.IsAny<T>())).Callback<T>(c => entities.Remove(c));
...
return repository;
}
While, "basically" correct, the reason I cannot mark either of the given answers as correct is they didn't offer-up a "full" solution to the problem (e.g. the ability to reference custom properties for testing).
There may be a better way to do this, but here is what worked for me...
DESIRED OUTCOME:
Mock my UnitOfWork (using Moq)
Mock all Repositories in my UnitOfWork (using Moq)
Use fake-or-pseudo records from properties in the mocks (like a database)
Take actual database concerns OUT of the equation
The hope was to make our Unit Tests much more "clean & seamless"
ACTUAL OUTCOME:
It was a complete success
Our tests are EXTREMELY clean, seamless & easy to create (see below)
OUTLINE OF THE SOLUTION:
Create a MockBuilder for each Repository (using Moq)
Create a MockBuilder for UnitOfWork (using Moq)
Let calls to the Builder take away all the complexities for us
ORIGINAL REPOSITORY INTERFACE:
This is the interface all our repositories use. So, all our 'builders' had to Mock.Setup all of these for each repository.
public interface IRepository<TEntity> where TEntity : class
{
#region <Methods>
IQueryable<TEntity> GetActive();
IQueryable<TEntity> GetAll();
TEntity GetById(object id);
TEntity Find(params object[] keyValues);
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Update(TEntity entity);
void Delete(TEntity entity);
void Delete(object id);
void ApplyState(TEntity entity, EntityState state);
EntityState GetState(TEntity entity);
#endregion
}
BUILDER INTERFACE:
public interface IBuilder
{
// Marker interface
}
REPOSITORY MOCK BUILDER INTERFACE:
public interface IRepositoryMockBuilder<TEntity> : IBuilder where TEntity : class
{
List<TEntity> Entities { get; }
EntityState EntityState { get; }
Mock<IRepository<TEntity>> CreateMock();
}
CONCRETE REPOSITORY MOCK BUILDER:
public class ClaimRepositoryMockBuilder : IRepositoryMockBuilder<Claim>
{
#region <Constructor>
public ClaimRepositoryMockBuilder(bool autoSeed)
{
Entities = AutoSeed(autoSeed);
EntityState = EntityState.Unchanged;
}
#endregion
#region <Properties>
public List<Claim> Entities { get; private set; }
public EntityState EntityState { get; private set; }
#endregion
#region <Methods>
public Mock<IRepository<Claim>> CreateMock()
{
var repository = new Mock<IRepository<Claim>>();
repository.SetupAllProperties();
repository.Setup(x => x.GetActive()).Returns(this.Entities.AsQueryable());
repository.Setup(x => x.GetAll()).Returns(this.Entities.AsQueryable());
repository.Setup(x => x.GetById(It.IsAny<object>())).Returns((object id) => { return this.Entities.Where(e => e.ClaimId == id.ToString()).FirstOrDefault(); });
repository.Setup(x => x.Find(new object[] { It.IsAny<string>() })).Returns((object id) => { return this.Entities.Where(e => e.ClaimId == id.ToString()).FirstOrDefault(); });
repository.Setup(x => x.Add(It.IsAny<Claim>())).Callback<Claim>(x => { this.Entities.Add(x); }).Verifiable();
repository.Setup(x => x.AddRange(It.IsAny<IEnumerable<Claim>>())).Callback<IEnumerable<Claim>>(x => { this.Entities.AddRange(x); }).Verifiable();
repository.Setup(x => x.Update(It.IsAny<Claim>())).Callback<Claim>(x => { UpdateEntity(x); }).Verifiable();
repository.Setup(x => x.Delete(It.IsAny<Claim>())).Callback<Claim>(x => { DeleteByEntity(x); }).Verifiable();
repository.Setup(x => x.Delete(It.IsAny<object>())).Callback<object>(x => { DeleteById(x); }).Verifiable();
repository.Setup(x => x.ApplyState(It.IsAny<Claim>(), It.IsAny<EntityState>())).Callback<Claim, EntityState>((x, y) => { this.EntityState = y; }).Verifiable();
repository.Setup(x => x.GetState(It.IsAny<Claim>())).Returns((Claim claim) => { return this.EntityState; });
return repository;
}
#region private
private void DeleteById(object id)
{
var entity = this.Entities.FirstOrDefault(x => x.ClaimId == id.ToString());
if (entity != null)
this.Entities.RemoveAt(Entities.IndexOf(entity));
}
private void DeleteByEntity(Claim deletedEntity)
{
var entity = this.Entities.FirstOrDefault(x => x.ClaimId == deletedEntity.ClaimId);
if (entity != null)
this.Entities.Remove(entity);
}
private void UpdateEntity(Claim updatedEntity)
{
var entity = this.Entities.FirstOrDefault(x => x.ClaimId == updatedEntity.ClaimId);
if (entity != null)
entity = updatedEntity;
}
private List<Claim> AutoSeed(bool autoSeed)
{
if (!autoSeed)
return new List<Claim>();
var database = new List<Claim>();
database.Add(new Claim()
{
// Set Properties Here
});
database.Add(new Claim()
{
// Set Properties Here
});
database.Add(new Claim()
{
// Set Properties Here
});
return database;
}
#endregion
#endregion
}
CONCRETE UNIT-OF-WORK MOCK BUILDER:
Add as many properties as you have repositories (we have a TON)
public class UnitOfWorkMockBuilder : IBuilder
{
#region <Constructors>
public UnitOfWorkMockBuilder(bool autoSeed)
{
ClaimsRepositoryBuilder = new ClaimsRepositoryMockBuilder(autoSeed);
SomeOtherRepositoryBuilder = new SomeOtherRepositoryMockBuilder(autoSeed);
}
#endregion
#region <Properties>
public ClaimsRepositoryMockBuilder ClaimsRepositoryBuilder { get; set; }
public SomeOtherRepositoryMockBuilder SomeOtherRepositoryBuilder { get; set; }
#endregion
#region <Methods>
public Mock<IMyUnitOfWork> CreateMock()
{
var unitOfWork = new Mock<IMyUnitOfWork>();
var depClaimTransactionsRepository = ClaimTransactionsRepositoryBuilder.CreateMock();
var depSomeOtherRepository = SomeOtherRepository.CreateMock();
unitOfWork.SetupAllProperties();
unitOfWork.Object.Claim = depClaimsRepositoryBuilder.Object;
unitOfWork.Object.SomeOther = depSomeOtherRepository.Object;
return unitOfWork;
}
#endregion
}
THE RESULTING UNIT TEST:
This is just one test, but ALL of out tests GREATLY cleaned up as a result of this effort.
[TestClass]
public class ClaimExistsRuleUnitTest
{
[TestMethod]
public void Returns_IsBau_When_Claim_DoesNotExist()
{
var builderUnitOfWork = new UnitOfWorkMockBuilder(true);
var claimId = "666";
var process = "MyAwesomeProcess";
// -----
// ARRANGE
// -----
var depUnitOfWork = builderUnitOfWork.CreateMock().Object;
var depProcess = depUnitOfWork.Processes.GetAll().Where(x => x.FriendlyName == process).First();
var depClaimMessage = new ClaimMessage();
var mockValidationResult = null as IValidationResult;
depClaimMessage.ClaimId = claimId;
depClaimMessage.StpClaimRequestProcessId = depProcess.Stp_Process_Code_Id;
// -----
// ACT
// -----
var rule = new ClaimExistsRule();
rule.UnitOfWork = depUnitOfWork;
mockValidationResult = rule.Validate(depClaimMessage);
// -----
// ASSERT
// -----
Assert.AreEqual(ClaimAction.IsBAU, mockValidationResult.Action);
}
#endregion
}

FakeItEasy - faking setter behaviour to store a value and then getter

Ultimately I want to have an internal interface with a setter and a public one with a getter. The code that replicates this scenario is roughed below:
[TestMethod]
public void TestMethod3()
{
var fake1 = A.Fake<IInterface1>(a => a.Implements(typeof(IInterface2)));
string backingString = null;
IInterface2 fake2 = (IInterface2)fake1;
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("set_Property"))
.Invokes((string param) => { backingString = param; });
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().Returns(backingString); //doesn't work
A.CallTo(fake2)
.Where(a => a.Method.Name.Equals("set_Property"))
.Invokes((string param) => { backingString = param; });
A.CallTo(fake2)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().Returns(backingString); //doesn't work
fake1.Property = "asdf";
Assert.AreEqual("asdf", fake1.Property); //fails -> fake1.Property is null
Assert.AreEqual(fake1.Property, fake2.Property); //fails -> fake2.Property is null
}
}
public interface IInterface1
{
string Property { get; set; }
}
public interface IInterface2
{
string Property { get; }
}
I could get as far as using backingString to store the setter, but when setting up the getter it doesn't work as I wanted it to.
I also tried something in the line of A.CallTo(() => fake1.Property).Returns(backingString) to no avail.
Would appreciate assistance of them experts :)
When you set up your
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().Returns(backingString);
(and similarly for fake2),
the value of backingString is null, so that's what's returned later on when you access the Property getter.
In order to return the value of backingString at the time the Property getter is called, you want ReturnsLazily.
Make this change in each place and the tests pass:
A.CallTo(fake1)
.Where(a => a.Method.Name.Equals("get_Property"))
.WithReturnType<string>().ReturnsLazily(() => backingString);

AutoMapper Map If Not Null, Otherwise Custom Convert

Here's my code:
Mapper.CreateMap<Foo, Foo2>()
.ForMember(dest => dest.Bar, opt => opt.MapFrom(src => src.Bar == null ? new BarViewModel() : src.Bar))
Basically, "BarViewModel" has a parameterless ctor which sets up properties in the class.
So i'm trying to say to AutoMapper:
If the value is null, then use the ctor for the class. otherwise use the mapping you have in place
The above is giving me a C# compiler error. And i'm guessing a cast wouldn't work either.
So is there a AutoMapper trick to do this?
Worst case i could remove that mapping for that property, and just do:
var mapped = Mapper.Map<Foo,Foo2>(src);
if (mapped.Bar == null) mapped.Bar = new BarViewModel();
But that's a tad ugly.
Ideas?
You can use custom value resolver. The following should work:
Mapper.CreateMap<Foo, Foo2>()
.ForMember(dest => dest.Bar, opt => opt.ResolveUsing(src => src.Bar == null ? new Bar() : Mapper.Map<Bar,Bar2>(src.Bar)))
Now you can use .NullSubstitute() to replace NULL value to some custom value in Automapper, e.g.:
CreateMap<SMModel, VM_SMModel>()
.ForMember(d => d.myDate, o => o.NullSubstitute(new DateTime(2017,12,12)));
As of Automapper 8, ResolveUsing is no longer an option but inline Func's, IValueResolver and IMemberValueResolver are 😊.
Inline Func Example
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Foo, FooViewModel>()
.ForMember(dest => dest.BarViewModel,
opt => opt.MapFrom((src, dest) =>
{
if (src.Bar == null)
return new BarViewModel ();
return Mapper.Map<Bar, BarViewModel>(src.Bar);
}));
cfg.CreateMap<Bar, BarViewModel>();
});
IMemberValueResolver Example
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Foo, FooViewModel>()
.ForMember(dest => dest.BarViewModel,
opt => opt.MapFrom<NullBarResolver, Bar>(src => src.Bar));
cfg.CreateMap<Bar, BarViewModel>();
});
public class NullBarResolver : IMemberValueResolver<object, object, Bar, BarViewModel>
{
public BarViewModel Resolve(object source, object destination, Bar sourceMember,
BarViewModel destMember, ResolutionContext context)
{
if (sourceMember == null)
return new BarViewModel();
return Mapper.Map(sourceMember, destMember);
}
}
There's some good documentation on Custom Value Resolvers here.
Working demo
I don't get a compiler error for the following:
public class Foo
{
public Bar Bar { get; set; }
}
public class Foo2
{
public Bar Bar { get; set; }
}
public class Bar
{
public int Id { get; set; }
public Bar()
{
Id = 3;
}
}
CreateMap<Foo, Foo2>()
.ForMember(
dest => dest.Bar,
opt => opt.MapFrom(src => src.Bar == null ? new Bar() : src.Bar));
...so I'm wondering if the problem is not actually with your mapping?
This can be done with the PreCondition() method. Here's an extension method I wrote to do this more easily:
public static IMappingExpression<TSource, TDestination> MapIf<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> map, Expression<Func<TDestination, object>> selector,
Func<TSource, bool> mapIfCondition, Expression<Func<TSource, object>> mapping)
{
map.ForMember(selector, c =>
{
c.MapFrom(mapping);
c.PreCondition(mapIfCondition);
});
return map;
}
Usage Example:
//if settings are null coming from the sender, then ignore them and keep the current settings
CreateMap<PresentationView, Presentation>()
.MapIf(x => x.Settings, x => x.Settings is not null, v => v.Settings!)

Categories

Resources