I have a solution with several projects. A business components project, an MVC web app, a DTO's and ViewModels project, a business component unit test project, and an MVC unit test project. All in all, not too unusual. The business component had a Service reference to several WCF endpoints. Within the business component, the data contracts from the WCF end points gets automapped using AutoMapper into the data necessary for the ViewModels. The problem I wanted to solve was that the data contract POCO's in the autogenerated WCF proxies are all PUBLIC, so when I reference my business component from my MVC web app (actually injected via StructureMap so I can use a mock business component if I need to), I have access to the WCF POCO's from within the web app. Since several other developers will be working on the web app, I'd prefer them not to be tempted to directly use the WCF POCO's but instead go through the business components. So I removed the service reference in the business components and instead added a script that invokes SVCUTIL with the /INTERNAL flag so that the autogenerated classes are marked INTERNAL instead of public. However, now AutoMapper won't map to/from my data contract POCO's.
I could not find any documentation that would show me how to get AutoMapper to work with INTERNAL properties, so I pulled the source from github and modified TypeInfo.cs so that it ignored Fields and included nonpublic members. Now my solution works perfectly, but feels pretty hackish having my own custom version of AutoMapper. It seems there should be a way to map from WCF data contract POCO's without them having to be PUBLIC. What am I missing?
Changed TypeInfo.cs
private IEnumerable<MemberInfo> GetAllPublicReadableMembers()
{
IEnumerable typesToScan = new[] { Type, Type.BaseType };
if (Type.IsInterface)
typesToScan = typesToScan.Concat(Type.GetInterfaces());
return typesToScan
.Where(x => x != null)
.SelectMany(x => x.FindMembers(MemberTypes.Property, //changed this
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, //and this
(m, f) =>
m is FieldInfo ||
(m is PropertyInfo && ((PropertyInfo)m).CanRead &&
!((PropertyInfo)m).GetIndexParameters().Any()), null));
}