如何在标记为Internal的属性上使用AutoMapper? [英] How can I use AutoMapper on properties marked Internal?

查看:115
本文介绍了如何在标记为Internal的属性上使用AutoMapper?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个项目的解决方案.一个业务组件项目,一个MVC Web应用程序,一个DTO和ViewModels项目,一个业务组件单元测试项目和一个MVC单元测试项目.总而言之,不是太不寻常.业务组件具有对多个WCF端点的Service引用.在业务组件中,使用AutoMapper将来自WCF端点的数据合同自动映射到ViewModels所需的数据中.我想解决的问题是,自动生成的WCF代理中的数据合同POCO都是PUBLIC,因此当我从MVC Web应用程序引用我的业务组件时(实际上是通过StructureMap注入的,因此如果需要,我可以使用模拟业务组件) ),我可以从网络应用程序中访问WCF POCO.由于其他几个开发人员将在Web应用程序上工作,因此我希望他们不要直接使用WCF POCO,而要遍历业务组件.因此,我删除了业务组件中的服务引用,而是添加了一个脚本,该脚本使用/INTERNAL标志调用SVCUTIL,以便自动生成的类被标记为INTERNAL而不是public.但是,现在AutoMapper不再与我的数据合同POCO映射.

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.

我找不到任何文档向我展示如何使AutoMapper能够使用INTERNAL属性,因此我从github上获取了源代码并修改了TypeInfo.cs,以便它忽略了Fields并包含了非公共成员.现在,我的解决方案可以完美地工作,但是拥有自己的自定义版本的AutoMapper会让您感到有些紧张.似乎应该有一种方法可以从WCF数据合同POCO进行映射,而不必将其设为PUBLIC.我想念什么?

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?

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)
        );
}

推荐答案

只需在initialize方法中设置配置对象的ShouldMapProperty属性.

Just set the ShouldMapProperty property of your configuration object in the initialize method.

这里是使用静态API的示例,但是,您应该能够通过使用非静态API以类似的方式实现相同的目的.

Here is an example using the static API, however, you should be able to achieve the same in a similar fashion by using the non-static API.

Mapper.Initialize(i =>
{
    i.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
    i.CreateMap<Source, Target>();                
});

如果使用配置文件,则必须将其放入构造函数中:

If you use a profile, this must go in the constructor:

public class MyProfile : Profile
{
    public MyProfile()
    {
        ShouldMapProperty = arg => arg.GetMethod.IsPublic || arg.GetMethod.IsAssembly;

        // The mappings here.
    }
}

这篇关于如何在标记为Internal的属性上使用AutoMapper?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆