10
votes

Automapper et est * Propriétés spécifiées

J'ai un groupe de classes de contrat de données générées xsd.exe qui pour tous les éléments facultatifs ont une paire de propriétés C # comme xxx pré>

de l'autre côté de l'arène de cartographie, j'ai une nullable int Like P>

int? Amount {get; set;}


1 commentaires

Je pense que cela pourrait aider ValueInjectTer.CodePlex.com/documentation , il vous suffit de spécifier un algorithme de mappage pour int to int? Une fois et l'utiliser pour les objets dont vous avez besoin, vous n'avez pas à créer des cartes pour chaque paire de types.


3 Réponses :


1
votes

Honnêtement, je n'ai aucune idée de savoir si COMASPAPPER le fera (puisque je n'utilise pas beaucoup automapper), mais je sais que Protobuf-Net prend en charge ces modèles, de sorte que vous puissiez utiliser sériializer.changetype ( obj) code> pour retourner entre eux.

La version actuelle em> est toutefois assez dépendante d'avoir des attributs (tels que [xmelement (commander = n)] code >) Sur les membres - je ne sais pas si cela provoque un problème? La version en cours em> prend en charge les types de vanille (sans attributs), mais ce n'est pas encore complet (mais bientôt). P>

Exemple: P>

[XmlType]
public class Foo
{
    [XmlElement(Order=1)]
    public int? Value { get; set; }
}
[XmlType]
public class Bar
{
    [XmlElement(Order = 1)]
    public int Value { get; set; }
    [XmlIgnore]
    public bool ValueSpecified { get; set; }
}
static class Program
{
    static void Main()
    {
        Foo foo = new Foo { Value = 123 };
        Bar bar = Serializer.ChangeType<Foo, Bar>(foo);
        Console.WriteLine("{0}, {1}", bar.Value, bar.ValueSpecified);

        foo = new Foo { Value = null };
        bar = Serializer.ChangeType<Foo, Bar>(foo);
        Console.WriteLine("{0}, {1}", bar.Value, bar.ValueSpecified);

        bar = new Bar { Value = 123, ValueSpecified = true };
        foo = Serializer.ChangeType<Bar, Foo>(bar);
        Console.WriteLine(foo.Value);

        bar = new Bar { Value = 123, ValueSpecified = false };
        foo = Serializer.ChangeType<Bar, Foo>(bar);
        Console.WriteLine(foo.Value);
    }
}


1 commentaires

@Marc, merci pour l'information - je ne savais pas sur Protobuf-net, je vais jeter un oeil.



2
votes

OK, hier, j'ai eu une brève discussion avec Jimmy Bogard, auteur de FadiaPaper et, fondamentalement, ce que je recherche n'est actuellement pas possible. Le soutien à de telles conventions sera mis en œuvre un peu de temps à l'avenir (si je l'ai bien compris correctement :)).


0 commentaires

-1
votes

Voici un exemple de mapper le modèle avec * Propriétés spécifiées (source) pour modéliser avec des propriétés nullables (destination). J'ai configuré la méthode de condition pour tous les membres, ce qui vérifiera si la propriété source a une propriété correspondante * spécifiée et si elle le fera, alors il vérifiera sa valeur. Si * la propriété spécifiée renvoie false code>, la condition n'est pas remplie et la mappage sera ignorée.

Vous pouvez faire la même chose dans d'autres directives, mais au lieu de lire * valeur de propriété spécifiée que vous devrez définir IT. P>

public void Configure(IMapperConfigurationExpression cfg)
{
    cfg.CreateMap<Source, Destination>()
        .ForAllOtherMembers(opt => opt.PreCondition((srcObj, context) => IsSpecified(srcObj, context, opt)));
}

public static bool IsSpecified<TSource, TDestination, TMember>(TSource source, ResolutionContext context, IMemberConfigurationExpression<TSource, TDestination, TMember> opt)
{
    var dstMemberPropertyInfo = opt.DestinationMember as PropertyInfo;

    // if destination member not nullable, then assume that source member won't have *Specified property
    if (!IsNullableType(dstMemberPropertyInfo.PropertyType))
        return true;

    var config = context.Mapper.ConfigurationProvider;
    var map = config.FindTypeMapFor<TSource, TDestination>();
    var propertyMap = map.PropertyMaps.FirstOrDefault(x => x.DestinationMember.Name == opt.DestinationMember.Name);
    var sourceMembers = new Queue<MemberInfo>(propertyMap.SourceMembers);
    var srcParentType = typeof(TSource);
    var srcParentObj = source as object;

    // get the source parent instance
    while (sourceMembers.Count > 1) // the last item in queue is the SourceMember itself
    {
        var srcParentPropertyInfo = sourceMembers.Dequeue() as PropertyInfo;
        srcParentType = srcParentPropertyInfo.PropertyType;
        srcParentObj = srcParentPropertyInfo.GetValue(srcParentObj);

        // the source parent is not defined, so we can skip this mapping
        if (srcParentObj == null)
            return false;
    }

    var srcMemberSpecifiedPropName = propertyMap.SourceMember.Name + "Specified";
    var srcMemberSpecifiedProp = srcParentType.GetProperty(srcMemberSpecifiedPropName);

    // if there is no *Specified property, then assume value is specified
    return srcMemberSpecifiedProp == null || (bool)srcMemberSpecifiedProp.GetValue(srcParentObj);
}

private bool IsNullableType(Type type) => IsGenericType(type, typeof(Nullable<>));

private bool IsGenericType(Type type, Type genericType) => IsGenericType(type) && type.GetGenericTypeDefinition() == genericType;

private bool IsGenericType(Type type) => type.GetTypeInfo().IsGenericType;


0 commentaires