У меня есть решение с несколькими проектами. Проект бизнес-компонентов, веб-приложение MVC, проект DTO и ViewModels, проект модульного тестирования бизнес-компонентов и проект модульного тестирования MVC. В общем, не так уж и необычно. Бизнес-компонент имел ссылку на несколько конечных точек WCF. Внутри бизнес-компонента контракты данных из конечных точек WCF автоматически преобразуются с помощью AutoMapper в данные, необходимые для ViewModels. Проблема, которую я хотел решить, заключалась в том, что POCO контракта данных в автоматически сгенерированных прокси-серверах WCF являются PUBLIC, поэтому, когда я ссылаюсь на свой бизнес-компонент из своего веб-приложения MVC (фактически вводится через StructureMap, поэтому я могу использовать фиктивный бизнес-компонент, если мне нужно ), У меня есть доступ к WCF POCO из веб-приложения. Поскольку над веб-приложением будут работать несколько других разработчиков, я бы предпочел, чтобы они не поддавались соблазну напрямую использовать WCF POCO, а вместо этого использовали бизнес-компоненты. Поэтому я удалил ссылку на службу в бизнес-компонентах и вместо этого добавил сценарий, который вызывает SVCUTIL с флагом / INTERNAL, чтобы автоматически сгенерированные классы были помечены как ВНУТРЕННИЕ, а не общедоступные. Однако теперь AutoMapper не будет сопоставляться с моим контрактом данных POCO.
Мне не удалось найти никакой документации, которая показала бы мне, как заставить AutoMapper работать с ВНУТРЕННИМИ свойствами, поэтому я вытащил источник из github и изменил TypeInfo.cs, чтобы он игнорировал поля и включал закрытые члены. Теперь мое решение работает отлично, но я чувствую себя довольно хакерским, имея собственную версию AutoMapper. Кажется, должен быть способ сопоставить POCO контракта данных WCF без необходимости быть PUBLIC. Что мне не хватает?
Изменен TypeInfo.cs
private IEnumerable<MemberInfo> GetAllPublicReadableMembers()
{
IEnumerable<Type> 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)
);
}