自定义延迟加载对象

时间:2017-03-06 08:20:37

标签: c# automapper

我有一个Person类,其中包含一个通过访问Item属性来延迟加载(自定义延迟加载)人员地址数据的属性。我希望它被映射到POCO类。怎么可能呢?

此外,只有在有数据(检查HasData属性)并且如果没有数据时映射为null,是否可以进行映射? 这些是源类:

public class SourcePerson
{
    public string Name { get; set; }

    public MyLazyLoadingObject<SourceAddress> Address;
}

public class SourceAddress
{
    public string City { get; set; }

    public string Country { get; set; }
}

这是自定义延迟加载类(简化):

public class MyLazyLoadingObject<T>
{
    private int? _id;
    private T _object;

    public T Item
    {
        get
        {
            if (!_object.IsReaded)
            {
                _object.Read();
            }

            return _object;
        }
    }

    public bool HasData
    {
        get
        {
            return _id.HasValue;
        }
    }

    // Other non-relevant properties and methods 
}

这些是目的地类:

public class DestinationPerson
{
    public string Name { get; set; }

    public DestinationAddress Address;
}

public class DestinationAddress
{
    public string City { get; set; }

    public string Country { get; set; }
}

2 个答案:

答案 0 :(得分:2)

在没有代码重复的情况下,无法找到设置从MyLazyLoadingObject<T>T然后T到某些TDestination的转换的传统方式。

但是使用一些手动表达式构建的自定义IObjectMapper实现可以完成这项工作。

这是构建映射表达式的类:

public class MyLazyLoadingObjectMapper : IObjectMapper
{
    public bool IsMatch(TypePair context)
    {
        return context.SourceType.IsGenericType && context.SourceType.GetGenericTypeDefinition() == typeof(MyLazyLoadingObject<>);
    }

    public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
    {
        var item = Expression.Property(sourceExpression, "Item");
        Expression result = item;
        if (item.Type != destExpression.Type)
        {
            var typeMap = configurationProvider.ResolveTypeMap(item.Type, destExpression.Type);
            result = Expression.Invoke(typeMap.MapExpression, item, destExpression, contextExpression);
        }
        // source != null && source.HasData ? result : default(TDestination)
        return Expression.Condition(
            Expression.AndAlso(
                Expression.NotEqual(sourceExpression, Expression.Constant(null)),
                Expression.Property(sourceExpression, "HasData")
            ),
            result,
            Expression.Default(destExpression.Type)
        );
    }
}

您只需将其注册到MapperRegistry

即可
AutoMapper.Mappers.MapperRegistry.Mappers.Add(new MyLazyLoadingObjectMapper());

当然会创建常规类型地图(我猜你已经这样做了):

cfg.CreateMap<SourceAddress, DestinationAddress>();
cfg.CreateMap<SourcePerson, DestinationPerson>();

答案 1 :(得分:1)

我已经这样做了:

cfg.CreateMap<SourcePerson, DestinationPerson>().ForMember(t => t.Address, o => o.MapFrom(s => (s.Address.HasData)? s.Address.Item : null));