我有几个项目的解决方案。业务组件项目,MVC Web应用程序,DTO和ViewModels项目,业务组件单元测试项目和MVC单元测试项目。总而言之,并非太不寻常。业务组件具有对多个WCF端点的服务引用。在业务组件中,使用AutoMapper将来自WCF端点的数据协定自动化为ViewModel所需的数据。我想解决的问题是自动生成的WCF代理中的数据契约POCO都是PUBLIC,所以当我从我的MVC Web应用程序引用我的业务组件时(实际上是通过StructureMap注入的,所以如果我需要,我可以使用模拟业务组件),我可以从网络应用程序中访问WCF POCO。由于其他几个开发人员将在Web应用程序上工作,我更希望他们不要试图直接使用WCF POCO,而是通过业务组件。所以我删除了业务组件中的服务引用,而是添加了一个脚本,该脚本使用/ INTERNAL标志调用SVCUTIL,以便自动生成的类被标记为INTERNAL而不是public。但是,现在AutoMapper不会映射到我的数据合同POCO的数据。
我找不到任何可以告诉我如何让AutoMapper使用INTERNAL属性的文档,所以我从github中提取源并修改了TypeInfo.cs,以便忽略Fields并包含非公共成员。现在我的解决方案完美无缺,但我自己定制版本的AutoMapper让人觉得非常hackish。似乎应该有一种方法来映射WCF数据合同POCO,而不必将它们作为PUBLIC。我错过了什么?
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));
}
答案 0 :(得分:7)
只需在初始化方法中设置配置对象的ShouldMapProperty
属性即可。
以下是使用静态API的示例,但是,您应该能够通过使用非静态API以类似的方式实现相同的功能。
Mapper.Initialize(i =>
{
i.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
i.CreateMap<Source, Target>();
});
答案 1 :(得分:1)
使用它。它适用于私人和内部领域。
http://ragingpenguin.com/code/privatefieldresolver.cs.txt
用法:
// in one library
public class Foo
{
internal string _bar = "some value";
}
// in another library
public class FooModel
{
public string Bar { get; set; }
}
Mapper.CreateMap<Foo, FooModel>()
.ForMember(x => x.Bar, o => o.ResolveUsing(new PrivateFieldResolver("_bar")));
像魅力一样。
答案 2 :(得分:0)
您是否考虑过映射到接口?让数据契约实现一个接口,然后只映射到那个。然后,您可以显式实现该接口,有效地隐藏这些成员。