问题
I have a following class structure:
class SrcChild
{
public bool SomeProperty { get; set; }
}
class SrcParent
{
public IEnumerable<SrcChild> Children { get; set; }
}
so the SrcParent has a collection of SrcChild objects.
Now I want to map an instance of SrcParent to DstParent. Here are the destination classes:
class DstChild
{
public bool SomeProperty { get; set; }
public DstChild(DstParent parent)
{
if (parent == null)
throw new ArgumentNullException();
}
}
class DstParent
{
public IEnumerable<DstChild> Children { get; set; }
}
The DstParent has a collection of DstChild objects, that use constructor injection to keep a reference to their parent.
Using AutoMapper, I tried the following:
class Program
{
static void Main(string[] args)
{
/* mapping configuration */
Mapper.CreateMap<SrcChild, DstChild>()
.ConstructUsing(
resolutionContext => new DstChild((DstParent)resolutionContext.Parent.DestinationValue));
Mapper.CreateMap<SrcParent, DstParent>();
/* source parent object with two children */
var srcParent = new SrcParent
{
Children = new[] { new SrcChild(), new SrcChild() }
};
/* throws an exception */
var dstParent = Mapper.Map<DstParent>(srcParent);
Console.ReadKey();
}
}
The main part here is the AutoMapper configuration where I am trying to extract reference to the produced DstParent from mapping context. This doesn't work (the (DstParent)resolutionContext.Parent.DestinationValue is null), but maybe I'm completely missing a point here?
Another idea I had was to use a function to create the child values, something like this:
class Program
{
/* Should produce value for DstParent.Children */
private static IEnumerable<DstChild> MakeChildren(SrcParent src /*, DstParent dstParent */)
{
var result = new List<DstChild>();
// result.Add(new DstChild(dstParent));
return result;
}
static void Main(string[] args)
{
/* mapping configuration */
Mapper.CreateMap<SrcChild, DstChild>();
Mapper.CreateMap<SrcParent, DstParent>()
.ForMember(dst => dst.Children,
opt => opt.MapFrom(src => MakeChildren(src /*, How to obtain a reference to the destination here? */)));
/* source parent object with two children */
var srcParent = new SrcParent
{
Children = new[] { new SrcChild(), new SrcChild() }
};
var dstParent = Mapper.Map<DstParent>(srcParent);
Console.ReadKey();
}
}
but I don't know how (if even possible at all) to get reference to the DstParent object produced by the Mapper.
Does anyone have an idea how to do this or should I rather think of dropping this design altogether and get rid of the parent reference? Thanks in advance.
回答1:
Ok, a solution that I found is not pretty, but it works:
class Program
{
static IEnumerable<DstChild> MakeChildren(IEnumerable<SrcChild> srcChildren, DstParent dstParent)
{
var dstChildren = new List<DstChild>();
foreach (SrcChild child in srcChildren)
{
var dstChild = new DstChild(dstParent);
Mapper.Map(child, dstChild);
dstChildren.Add(dstChild);
}
return dstChildren;
}
static void Main(string[] args)
{
Mapper.CreateMap<SrcChild, DstChild>();
Mapper.CreateMap<SrcParent, DstParent>()
/* Ignore Children property when creating DstParent*/
.ForMember(dst => dst.Children, opt => opt.Ignore())
/* After mapping is complete, populate the Children property */
.AfterMap((srcParent, dstParent) =>
{
dstParent.Children = MakeChildren(srcParent.Children, dstParent);
});
var source = new SrcParent
{
Children = new[]
{
new SrcChild() {SomeProperty = true},
new SrcChild() {SomeProperty = false}
}
};
var destination = Mapper.Map<DstParent>(source);
Console.ReadKey();
}
}
The destination has children initialized, with SomeProperty properly assigned by AutoMapper. Please let me know if you find a better looking solution.
来源:https://stackoverflow.com/questions/34290431/mapping-child-classes-with-parent-injected-in-the-constructor-using-automapper