如何在标记为Internal的属性上使用AutoMapper?

时间:2010-07-08 21:14:45

标签: automapper

我有几个项目的解决方案。业务组件项目,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。我错过了什么?

更改了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));
 }

3 个答案:

答案 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)

您是否考虑过映射到接口?让数据契约实现一个接口,然后只映射到那个。然后,您可以显式实现该接口,有效地隐藏这些成员。