#StackBounty: #c# #dapper Mapper made specifically to work with Dapper

Bounty: 200

I needed a mapper for a project I have using Dapper. I tried Automapper and other tools that comes with Dapper (Contrib, Rainbow, etc.), but I couldn’t make Automapper work properly and the rest doesn’t have what I need, so I did one.
Take in mind that I’m an amateur and not native english speaker πŸ˜‰

The whole thing is in GitHub, I’ll write down here what I can, but it’s large, it won’t fit the code limit so there’s the link to the whole thing.
It works and in my tests it maps each object in about 2 milliseconds… it worry me, it’s too much good.
To be honest, given that I’m an amateur and after reading lots about reflection performance overhead, I was “mentally prepared” to lose performance for the sake of having it working the way I wanted and what not, so now I’m worried if I’m overlooking something and will appreciate any advice.

I’m sorry, I tried to summarize the post but I can’t summarize it any more, remember english is not my native language, and again the whole thing doesn’t fit here. If you want to help (thanks you) or it interests you, you can just take a peek at the Github link I provided earlier and come back to read what you need from the rest, if you need it.

Just to be sure, both in code and here I’ll refer as “Dapper’s dynamic result” to the result of the query Dapper returns. I don’t know if it’s really suitable, but it’s easier to me to name it that way.
Also, there’s a general diagram I did to have things clearer myself: in google drive.

The mapper works given some static dictionaries that stores information about the types that will be mapped, using a configuration the user have to make before map any object (at the app beginning… similar to Automapper I think).
I divided the different dictionaries in different usual public classes, so each class of the mapper can inherit only what’s needed, f.i.:

public class DMStatic_Dictionary : MQBStatic_IEnumerable
{
    public DMStatic_Dictionary(string[] customNamespaces = null) : base(customNamespaces)
    {
        InitStaticDDictionary();
    }

    #region fields
    protected static Dictionary<Type, Dictionary<string, string[]>> _Dictionaries;
    #endregion

    #region helpers
    private static void InitStaticDDictionary()
    {
        if (_Dictionaries == null)
        {
            lock (_LockObject)
            {
                if (_Dictionaries == null)
                    _Dictionaries = new Dictionary<Type, Dictionary<string, string[]>>();
            }
        }
    }
    #endregion
}

They store all the information, all the members, if each member is built-in, nested or a dictionary, prefixes and suffixes for searching later through the Dapper’s dynamic result, members to ignore, etc. Lets say they are just static dictionaries with the “reflection information” of the types (nested types, enumerables, dictionaries, etc.), so I don’t have to spend resources to retrieve that information at run time.


MAPPERCONFIG

As I said, the dictionaries should be filled at the very start of the app. To do that I made a fluent type class called MapperConfig.
This class do several things.

  • First it populates some static dictionaries through the public methods, f.i.:
    public MapperConfig AddNestedProperty<T>(bool isAnInterface, string memberName)
    {
        Type destination = typeof(T);
    
        if (_OnlyConstructor.Contains(destination))
            throw new CustomException_MapperConfig(
                @"MapperConfig.AddNestedProperty: You can't any configuration if MapOnlyConstructor have been setted.");
        if (_MembersCreators.ContainsKey(destination) && _MembersCreators[destination].ContainsKey(memberName))
            throw new CustomException_MapperConfig(
                $@"MapperConfig.AddNestedProperty: One member({memberName}) can not have a creator expression AND be setted as a nested type at same type");
        if (_Ignores.ContainsKey(destination) && _Ignores[destination].Contains(memberName))
            throw new CustomException_MapperConfig(
                $@"MapperConfig.AddNestedProperty: One member({memberName}) can not be setted as nested property if it was setted for ignore.");
    
        if (isAnInterface)
        {
            lock (_LockObject)
            {
                if (!_Interfaces.ContainsKey(destination))
                    _Interfaces.Add(destination, new List<string>() { memberName });
                else if (!_Interfaces[destination].Contains(memberName))
                    _Interfaces[destination].Add(memberName);
            }
        }
    
        lock (_LockObject)
        {
            if (!_NestedProperties.ContainsKey(destination))
            {
                _NestedProperties.Add(destination, new List<string>() { memberName });
                return this;
            }
            else
            {
                if (!_NestedProperties[destination].Contains(memberName))
                    _NestedProperties[destination].Add(memberName);
                return this;
            }
        }
    }
    

    This public methods are how one tell the mapper how to map each type member, if it’s a nested type (AddNestedProperty), if it’s a dictionary (AddDictionary), if it has to run some Func with the Dapper’s dynamic result to create the member (AddMemberCreator), if it has to use a constructor (AddConstructor, works via a Func again), etc.
    I wrote the ones I think I’ll need and others more general. Some notes about them:

    IEnumerable members are automated, the mapper will identify and map them automatically therefore there’s no need to configure them and no method in this class for them, but I didn’t find a way to automate dictionaries so I did a specific method to declare an object member as a dictionary to map it later: one need to pass the names that keys and values will have at the Dapper’s dynamic result, so the mapper can find them at runtime. If keys or values (or both) are custom, nested types, one have to configure the member as a nested property too:

    .AddNestedProperty<Finca>(false, "_Cuotas") 
    .AddDictionary<Finca>("_Cuotas", new string[2] { "cuotaId", "Cuota" })
    

    The mapper will find what’s nested (keys, values or both), map the built-in types using the name provided, ignore the name of the nested type and map the nested type recursively with a new mapper.

    Other note: as you probably have noted, a single member can be declared as various things, for instance (again) if a member is of type Dictionary<MyClass, int>, not only it can be declared as dictionary and nested, it MUST be declared as both of them or later the mapper will try to map keys as a built-in type and throw an exception.

  • Second it populates more static dictionaries with reflection. I didn’t want to search and retrieve all member of all objects-to-map at run time, so I store every member of the objects configured in the dictionaries:
    protected static Dictionary<Type, PropertyInfo[]> _QBPropertyInfos;
    protected static Dictionary<Type, FieldInfo[]> _QBFieldInfos;
    

    This is done in the method private void SetMembersInformation(Type t) of the MapperConfig class:

    private void SetMembersInformation(Type t)
    {
        if (_OnlyConstructor.Contains(t))
            RemoveAllConfigExceptConstructor(t);
    
        var pInfos = t.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
            .Where(pInfo => pInfo.GetSetMethod() != null)
            .ToList();
        var fInfos = t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
            //http://stackoverflow.com/questions/40820102/reflection-returns-backing-fields-of-read-only-properties
            .Where(fInfo => fInfo.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
            .ToList();
    
        //Get all inherited fields up the hierarchy => BindingFlags.FlattenHierarchy only works with public members
        bool inheritance = t.BaseType != null;
        Type inheritedT = t;
        Type baseT;
        while (inheritance)
        {
            //inherited fields
            baseT = inheritedT.BaseType;
            var baseFInfos = baseT.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
                .Where(fInfo => fInfo.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
                .ToList();
            fInfos = fInfos.Union(baseFInfos).ToList();
    
            //inherit mapper configurations
            MapperStore store = new MapperStore();
            if (store.GetMapper(baseT) != null)
                CopyConfigurations(baseT, t);
    
            inheritance = baseT.BaseType != null;
            inheritedT = baseT;
        }
    
        IEnumerable<MemberInfo> mInfos = pInfos.Union((IEnumerable<MemberInfo>)fInfos);
        Dictionary<MemberInfo, MemberTypeInfo> preMTInfos = (Dictionary<MemberInfo, MemberTypeInfo>)mInfos
            .Select(x =>
            {
                if (_Ignores.ContainsKey(t) && _Ignores[t].Contains(x.Name))
                    return new KeyValuePair<MemberInfo, MemberTypeInfo>(x, MemberTypeInfo.Ignore);
                else return new KeyValuePair<MemberInfo, MemberTypeInfo>(x, MemberTypeInfo.BuiltIn);
            })
            .ToDictionary(x => x.Key, x => x.Value);
    
        //prevent collection was modified exception
        Dictionary<MemberInfo, MemberTypeInfo> changes = new Dictionary<MemberInfo, MemberTypeInfo>(preMTInfos);
    
        IEnumerable<string> preNamesList = pInfos
            .Where(pInfo => preMTInfos[pInfo] != MemberTypeInfo.IEnumerable)
            .Select(pInfo => pInfo.Name)
            .Union(fInfos
                .Where(pInfo => preMTInfos[pInfo] != MemberTypeInfo.IEnumerable)
                .Select(fInfo => fInfo.Name));
    
        //Store all MemberTypeInfo
        //Trying to save iterations doing first if dictionary.contains(type)
        if (_MembersCreators.ContainsKey(t) && _NestedProperties.ContainsKey(t))
        {
            //Set members type dictionary
            foreach (KeyValuePair<MemberInfo, MemberTypeInfo> kvp in preMTInfos.Where(kvp => kvp.Value != MemberTypeInfo.Ignore))
            {
                if (_MembersCreators[t].ContainsKey(kvp.Key.Name))
                {
                    if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = MemberTypeInfo.Creator;//_preMTInfos[kvp.Key] = MemberTypeInfo.Creator;
                    RemoveMember(kvp.Key, pInfos, fInfos);
                }
                else
                {
                    if (_NestedProperties[t].Contains(kvp.Key.Name))
                    {
                        if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = MemberTypeInfo.Nested;//_preMTInfos[kvp.Key] = MemberTypeInfo.Nested;
                        RemoveMember(kvp.Key, pInfos, fInfos);
                    }
    
                    Type mType = GetMemberType(kvp.Key);
                    if (typeof(IEnumerable).IsAssignableFrom(mType) && !typeof(string).IsAssignableFrom(mType))
                    {
                        if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = changes[kvp.Key] | MemberTypeInfo.IEnumerable; //_preMTInfos[kvp.Key] = _preMTInfos[kvp.Key] | MemberTypeInfo.IEnumerable;
                        RemoveMember(kvp.Key, pInfos, fInfos);
                    }
                }
            }
        }
        else if (_MembersCreators.ContainsKey(t))
        {
            //Set members type dictionary
            foreach (KeyValuePair<MemberInfo, MemberTypeInfo> kvp in preMTInfos.Where(kvp => kvp.Value != MemberTypeInfo.Ignore))
            {
                if (_MembersCreators[t].ContainsKey(kvp.Key.Name))
                {
                    if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = MemberTypeInfo.Creator; //_preMTInfos[kvp.Key] = MemberTypeInfo.Creator;
                    RemoveMember(kvp.Key, pInfos, fInfos);
                }
                else
                {
                    Type mType = GetMemberType(kvp.Key);
                    if (typeof(IEnumerable).IsAssignableFrom(mType) && !typeof(string).IsAssignableFrom(mType))
                    {
                        if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = changes[kvp.Key] | MemberTypeInfo.IEnumerable; //_preMTInfos[kvp.Key] = _preMTInfos[kvp.Key] | MemberTypeInfo.IEnumerable;
                        RemoveMember(kvp.Key, pInfos, fInfos);
                    }
                }
            }
        }
        else if (_NestedProperties.ContainsKey(t))
        {
            //Add to members names list
            preNamesList = preNamesList.Union(_NestedProperties[t]);
    
            //Set members type dictionary
            foreach (KeyValuePair<MemberInfo, MemberTypeInfo> kvp in preMTInfos.Where(kvp => kvp.Value != MemberTypeInfo.Ignore))
            {
                if (_NestedProperties[t].Contains(kvp.Key.Name))
                {
                    if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = MemberTypeInfo.Nested; //_preMTInfos[kvp.Key] = MemberTypeInfo.Nested;
                    RemoveMember(kvp.Key, pInfos, fInfos);
                }
    
                Type mType = GetMemberType(kvp.Key);
                if (typeof(IEnumerable).IsAssignableFrom(mType) && !typeof(string).IsAssignableFrom(mType))
                {
                    if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = changes[kvp.Key] | MemberTypeInfo.IEnumerable; //_preMTInfos[kvp.Key] = _preMTInfos[kvp.Key] | MemberTypeInfo.IEnumerable;
                    RemoveMember(kvp.Key, pInfos, fInfos);
                }
            }
        }
        //built-in
        else if (!_OnlyConstructor.Contains(t))
        {
            //Set members type dictionary
            foreach (KeyValuePair<MemberInfo, MemberTypeInfo> kvp in preMTInfos.Where(kvp => kvp.Value != MemberTypeInfo.Ignore))
            {
                Type mType = GetMemberType(kvp.Key);
                if (typeof(IEnumerable).IsAssignableFrom(mType) && !typeof(string).IsAssignableFrom(mType))
                    changes[kvp.Key] = MemberTypeInfo.IEnumerable; //_preMTInfos[kvp.Key] = MemberTypeInfo.IEnumerable;
            }
        }
    
        if (_Interfaces.ContainsKey(t))
        {
            //Set members type dictionary
            foreach (KeyValuePair<MemberInfo, MemberTypeInfo> kvp in preMTInfos.Where(kvp => kvp.Value != MemberTypeInfo.Ignore))
            {
                if (_Interfaces[t].Contains(kvp.Key.Name))
                {
                    if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = changes[kvp.Key] | MemberTypeInfo.Interface;
                    RemoveMember(kvp.Key, pInfos, fInfos);
                }
    
                Type mType = GetMemberType(kvp.Key);
                if (typeof(IEnumerable).IsAssignableFrom(mType) && !typeof(string).IsAssignableFrom(mType))
                {
                    if (!_OnlyConstructor.Contains(t)) changes[kvp.Key] = changes[kvp.Key] | MemberTypeInfo.IEnumerable; //_preMTInfos[kvp.Key] = _preMTInfos[kvp.Key] | MemberTypeInfo.IEnumerable;
                    RemoveMember(kvp.Key, pInfos, fInfos);
                }
            }
        }
    
        //Lock-static dictionaries
        lock (_LockObject)
        {
            if (!_mtInfos.ContainsKey(t)) _mtInfos.Add(t, changes);
            else _mtInfos[t] = changes;
    
            if (!_NamesList.ContainsKey(t)) _NamesList.Add(t, preNamesList);
            else _NamesList[t] = preNamesList;
    
            if (!_QBPropertyInfos.ContainsKey(t)) _QBPropertyInfos.Add(t, pInfos.ToArray());
            else _QBPropertyInfos[t] = pInfos.ToArray();
    
            if (!_QBFieldInfos.ContainsKey(t)) _QBFieldInfos.Add(t, fInfos.ToArray());
            else _QBFieldInfos[t] = fInfos.ToArray();
    
            string columns = "";
            var orderedMembersNames = _QBPropertyInfos[t].Select(x => x.Name)
                .Union(_QBFieldInfos[t].Select(x => QBuilder.StringSQLBuilder.RemoveFieldsUnderscore(x.Name)))
                .OrderBy(x => x);
            columns = string.Join(",", orderedMembersNames);
    
            if (!_Columns.ContainsKey(t)) _Columns.Add(t, columns);
            else _Columns[t] = columns;
        }
    }
    

    It iterates through all members of the given type (and parent classes), storing them, determining who are an IEnumerable and filling another important dictionary:

    protected static Dictionary<Type, Dictionary<MemberInfo, MemberTypeInfo>> _mtInfos;
    

    Which is just a fast way to determine at runtime what have to do the mapper.
    MemberTypeInfo is an Enum:

    [Flags]
    public enum MemberTypeInfo { BuiltIn = 1, Nested = 2, Creator = 4, IEnumerable = 8, Dictionary = 16, Interface = 32, Ignore = 64 }
    

    So, at runtime the mapper looks at this dictionary for every member, and does whatever it has to do, e.g. if the member is a nested type it calls another mapper recursively to map the member, and if it’s built-in type it just search the value in the given Dapper dynamic result by the member’s name and sets it.
    The configurations of the parent classes are inherited too through the private void CopyConfigurations(Type baseT, Type nestedT) method, so one can configure a parent class completely (even an abstract class), and then configure all the child class without having to repeat the parent’s things, since all child will automatically inherit parent configurations.

There’re some obvious configurations like AddNestedProperty or IgnoreProperty, and others not so obvious like AddInterfaceToObjectCondition but I think that the methods comments are enough to understand what they all do.
If that’s not the case I’ll explain anything, just ask it.

Just to note a pair of rules here (or flaws…):

  1. The method EndConfig() must be called for every type that will have to be mapped, even nested types, interfaces, structs, everything. Even if the type have only built in types and needs no other configuration. The mapper only “see” what’s configured, if EndConfig() doesn’t get called for a type, that type doesn’t exist for the mapper.
  2. The same method must be called after all configurations for that type have been called. Given that it’s fluent type, the last method for a type configuration should be always EndConfig(). Take in mind that the method SetMembersInformation compares members with what the user stored in dictionaries, so if that method is called various times, I have no idea what could happen, it’s not prepared for that.
  3. I wouldn’t make configurations at run time. The system haven’t been made for that, I haven’t tested it and I have no ides what would happen. Maybe it’d work flawlessly, or maybe not.

A pair of example of some configurations of my own project:

//A pair of easy ones
            mConfig
                .AddNestedProperty<Apunte>(false, "_Asiento")
                .AddMemberCreator<Apunte>("_DebeHaber", x => (DebitCredit)x.DebeHaber)
                .AddPrefixes<Apunte>(new string[] { "apu" })
                .EndConfig<Apunte>();
            mConfig
                .AddConstructor<ApunteDLO>(x => new ApunteDLO(x.Id, x.IdOwnerComunidad, x.OrdenEnAsiento, x.Asiento, x.Concepto, x.DebeHaber,
                    x.Importe, x.IdCuenta, x.Punteo, x.Factura))
                .MapOnlyConstructor<ApunteDLO>()
                .EndConfig<ApunteDLO>();

...

//More complicated
            mConfig
                .AddConstructor<Finca>(x => new Finca(x.Id, x.IdOwnerComunidad, x.Baja, x.Nombre, x.Coeficiente, x.Codigo, this.ACData))
                .AddNestedProperty<Finca>(false, "_PropietarioActual")
                .AddDictionary<Finca>("_HistoricoPropietarios", new string[2] { "FechaFinal", "IdPropietario" })
                .AddNestedProperty<Finca>(false, "_Cuotas")
                .AddDictionary<Finca>("_Cuotas", new string[2] { "cuotaId", "Cuota" })
                .AddNestedProperty<Finca>(false, "_EntregasACuenta")
                .AddNestedProperty<Finca>(false, "_Devoluciones")
                .AddNestedProperty<Finca, DireccionPostal>(false, x => x.Direccion)
                .AddMemberCreator<Finca, DireccionPostal>(x => x.Direccion2,
                    x => new DireccionPostal(x.TipoVia2, x.Direccion2, x.CP2, x.Localidad2, x.Provincia2))
                .AddMemberCreator<Finca, TipoPagoCuotas>(x => x.DefaultTipoPagoCuotas, x => (TipoPagoCuotas)x.DefaultTipoPagoCuotas)
                .AddMemberCreator<Finca, sTelefono>(x => x.Telefono1, x => new sTelefono(x.Telefono, x.TipoTelefono))
                .AddMemberCreator<Finca, sTelefono>(x => x.Telefono2, x => new sTelefono(x.Telefono2, x.TipoTelefono2))
                .AddMemberCreator<Finca, sTelefono>(x => x.Telefono3, x => new sTelefono(x.Telefono3, x.TipoTelefono3))
                .AddMemberCreator<Finca, sTelefono>(x => x.Fax, x => new sTelefono(x.Fax, TipoTelefono.Fax))
                .AddMemberCreator<Finca, int[]>(x=>x.IdAsociadas, x=>
                {
                    IEnumerable<dynamic> ex = (IEnumerable<dynamic>)x;
                    return ex
                        .Select(dyn => dyn.IdFincaAsociada)
                        .Distinct()
                        .ToArray();
                })
                .AddMemberCreator<Finca>("_IdCopropietarios", x =>
                {
                    IEnumerable<dynamic> ex = (IEnumerable<dynamic>)x;
                    return ex
                        .Select(dyn => dyn.IdPersonaCoProp)
                        .Distinct()
                        .ToArray();
                })
                .AddMemberCreator<Finca>("_IdPagadores", x =>
                {
                    IEnumerable<dynamic> ex = (IEnumerable<dynamic>)x;
                    return ex
                        .Select(dyn => new Tuple<int, TipoPagoCuotas>(dyn.IdPersonaCoPag, (TipoPagoCuotas)dyn.TipoPagoCuotas))
                        .Distinct()
                        .ToArray();
                })
                .EndConfig<Finca>();

MAPPERSTORE

I thought it would be a waste to create mappers all around the app, so I just created a little class called MapperStore to store and retrieve mappers already created, using a static dictionary to store mappers as interfaces.

/// <summary>
/// Use this to get DapperMapper objects.
/// </summary>
public class MapperStore : DMStatic_Store
{
    /// <summary>
    /// Store t as a type that can be, and has been configured for mapping by DapperMapper. If you are configuring a type, use 
    /// MapperConfig.EndCongfig<type>() instead.
    /// Don't use it before configuring the mapper first.
    /// </summary>
    /// <param name="t"></param>
    public void StoreType(Type t)
    {
        if (!_TypesToMap.Contains(t))
            _TypesToMap.Add(t);
    }
    /// <summary>
    /// Store a mapper object in static dictionary.
    /// </summary>
    /// <param name="t"></param>
    /// <param name="mapper"></param>
    public void StoreMapper(Type t, iDapperMapper mapper)
    {
        if (!_Mappers.ContainsKey(t)) _Mappers.Add(t, mapper);
    }
    /// <summary>
    /// Get mapper of type t. If type t hasn't been stored by StoreType, returns null. If type t has been stored and there are no mappers
    /// created yet, it creates a new one, stores it, and return it.
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    public iDapperMapper GetMapper(Type t)
    {
        if (_Mappers.ContainsKey(t))
            return _Mappers[t];

        if (!_TypesToMap.Contains(t))
            return null;

        iDapperMapper mapper = (iDapperMapper)Activator.CreateInstance(typeof(DapperMapper<>).MakeGenericType(t), this);
        StoreMapper(t, mapper);
        return mapper;
    }
    /// <summary>
    /// Returns true if a mapper exists or can be created, and set it as iDapperMapper.
    /// If type t hasn't been stored by StoreType, returns false. If type t has been stored and there are no mappers
    /// created yet, it creates a new one, stores it, set it as iDapperMapper and returns true.
    /// </summary>
    /// <param name="t"></param>
    /// <param name="mapper"></param>
    /// <returns></returns>
    public bool GetMapper(Type t, out iDapperMapper mapper)
    {
        if (_Mappers.ContainsKey(t))
        {
            mapper = _Mappers[t];
            return true;
        }

        if (!_TypesToMap.Contains(t))
        {
            mapper = null;
            return false;
        }

        mapper = (iDapperMapper)Activator.CreateInstance(typeof(DapperMapper<>).MakeGenericType(t), this);
        StoreMapper(t, mapper);
        return false;
    }
    /// <summary>
    /// Remove mapper previously stored.
    /// </summary>
    /// <param name="t"></param>
    public void RemoveMapper(Type t)
    {
        if (_Mappers.ContainsKey(t))
            _Mappers.Remove(t);
    }
}

And the expected way to get a mapper:

MapperStore store = new MapperStore();
DapperMapper<Foo> mapper = (DapperMapper<Foo>)store.GetMapper(typeof(Foo));

DAPPERMAPPER

And here’s the thing finally, it’s the class that actually map the objects, usually through this method:

        public T Map(IEnumerable<dynamic> dapperResult, bool cleanResult = false)
        {
            var parser = new PrePostFixesParser(this);
            T mapped = this.NewObject(dapperResult.First());
            if (_OnlyConstructor.Contains(this.TType)) return mapped;

            //TODO: divide el siguiente foreach en dos con dos nuevos diccionarios estΓ‘ticos, uno para pInfos y otro para fInfos, 
            //aunque se repita cΓ³digo: hacer mΓ©todos para cada parte del cΓ³digo del tipo:
            //private T PreMapCreator(KeyValuePair<PropertyInfo, MemberTypeInfo> kvp, IEnumerable<dynamic> dapperResult, bool cleanResult = false)
            //private T PreMapIEnumerable(KeyValuePair<PropertyInfo, MemberTypeInfo> kvp, IEnumerable<dynamic> dapperResult, bool cleanResult = false)
            //...

            //Loop through all members
            foreach (KeyValuePair<MemberInfo, MemberTypeInfo> kvp in mtInfos)
            {
                if (kvp.Value == MemberTypeInfo.Ignore)
                    continue;
                //Member have a creator
                else if ((kvp.Value & MemberTypeInfo.Creator) == MemberTypeInfo.Creator)
                {
                    //MemberDelegate mDel = (MemberDelegate)_MembersCreators[this.TType][kvp.Key.Name];
                    Func<dynamic, object> mDel = (Func<dynamic, object>)_MembersCreators[this.TType][kvp.Key.Name];

                    if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, mDel(dapperResult));
                    else ((FieldInfo)kvp.Key).SetValue(mapped, mDel(dapperResult));
                }
                //Member is IDictionary or IEnumerable
                else if ((kvp.Value & MemberTypeInfo.IEnumerable) == MemberTypeInfo.IEnumerable)
                {
                    Type t = GetMemberType(kvp.Key);
                    //if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface) t = ResolveInterface(kvp.Key, dapperResult);
                    //else t = GetMemberType(kvp.Key);
                    /*
                    {
                        //Type of property or field
                        if (kvp.Key.MemberType == MemberTypes.Property) t = ((PropertyInfo)kvp.Key).PropertyType;
                        else t = ((FieldInfo)kvp.Key).FieldType;
                    }*/
                    bool isAnInterface = (kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface;
                    bool isNested = (kvp.Value & MemberTypeInfo.Nested) == MemberTypeInfo.Nested;

                    //If member is a dictionary
                    if (typeof(IDictionary).IsAssignableFrom(t))
                    {
                        //Create a dummy dictionary with the dapper's dynamic result which should be equal to the final one
                        DictionaryMapper dictMapper = new DictionaryMapper(dapperResult, kvp.Key.Name, isNested, isAnInterface, cleanResult, t, this);

                        try
                        {
                            if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, dictMapper.DummyDictionary);
                            else ((FieldInfo)kvp.Key).SetValue(mapped, dictMapper.DummyDictionary);
                        }
                        catch (Exception err)
                        {
                            throw new CustomException_DapperMapper(
                                $@"DapperMapper.Map: Couldn't map IDictionary member {kvp.Key.Name} with value contained by dynamic object.
Incorrect type of value?: {kvp.Value.ToString()}",
                                err);
                        }
                    }
                    //Rest of enumerables
                    else
                    {
                        IEnumerable<dynamic> iEnumDapperResult;
                        //Select current member's values from dynamic
                        if (isNested && !cleanResult)
                        {
                            //Type mType = t; // GetMemberType(kvp.Key);//IEnumerable<T>
                            Type genericType = t.GenericTypeArguments[0];//mType.GenericTypeArguments[0];//T
                            if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface)
                            {
                                bool genericIsInterfaceNotIEnumerable =
                                    genericType.IsInterface &&
                                    !typeof(IDictionary).IsAssignableFrom(genericType) &&
                                    !(typeof(IEnumerable).IsAssignableFrom(genericType) && !typeof(string).IsAssignableFrom(genericType));

                                if (genericIsInterfaceNotIEnumerable) genericType = ResolveInterface(genericType, dapperResult);
                            }

                            iDapperMapper nestedMapper = MappersStore.GetMapper(genericType);
                            var nestedParser = new PrePostFixesParser(nestedMapper);

                            iEnumDapperResult = dapperResult
                                .Select(dyn => nestedParser.GetTypeMembersWithoutPrePostFixes(dyn, nestedMapper.NamesList));
                        }
                        else if (!cleanResult) iEnumDapperResult = dapperResult.Select(dyn => parser.RemovePrePostFixesFromDictionary(dyn));
                        else iEnumDapperResult = dapperResult;

                        //Create dummy IEnumerable
                        EnumerableMapper enumMapper = new EnumerableMapper(iEnumDapperResult, kvp.Key.Name, isNested, t, this.TType); ;
                        var dummy = Activator.CreateInstance(t, enumMapper.DummyEnumerable);

                        try
                        {
                            if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, dummy);
                            else ((FieldInfo)kvp.Key).SetValue(mapped, dummy);
                        }
                        catch (Exception err)
                        {
                            throw new CustomException_DapperMapper(
                                $@"DapperMapper.Map: Couldn't map IEnumerable member {kvp.Key.Name} with value contained by dynamic object.
Incorrect type of value?: {kvp.Value.ToString()}",
                                err);
                        }
                    }
                }//End IDictionary/IEnumerable
                //If Built-in
                else if ((kvp.Value & MemberTypeInfo.BuiltIn) == MemberTypeInfo.BuiltIn)
                {
                    string name = parser.RemoveFieldsUnderscore(kvp.Key.Name);
                    IDictionary<string, object> dapperDict;
                    if (!cleanResult)
                        dapperDict = parser.GetTypeMembersWithoutPrePostFixes(dapperResult.First(), NamesList) as IDictionary<string, object>;
                    else
                        dapperDict = dapperResult.First() as IDictionary<string, object>;

                    if (!dapperDict.ContainsKey(name))
                        throw new CustomException_DapperMapper(
                            $@"DapperMapper.Map: There's no member in dynamic dapper result with name {kvp.Key.Name}. Cannot Map object.");

                    try
                    {
                        if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, dapperDict[name]);
                        else ((FieldInfo)kvp.Key).SetValue(mapped, dapperDict[name]);
                    }
                    catch (Exception err)
                    {
                        throw new CustomException_DapperMapper(
                            $@"DapperMapper.Map: Couldn't map BuiltIn-type member {kvp.Key.Name} with value contained by dynamic object.
Incorrect type of value?: {kvp.Value.ToString()}",
                            err);
                    }
                }
                //if nested
                else if ((kvp.Value & MemberTypeInfo.Nested) == MemberTypeInfo.Nested)
                {
                    Type mType = GetMemberType(kvp.Key);

                    if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface)
                        mType = ResolveInterface(mType, dapperResult);

                    //access generic Map method through nongeneric interface method
                    iDapperMapper nestedMapper = MappersStore.GetMapper(mType);

                    if (nestedMapper == null)
                        throw new CustomException_DapperMapper(
                            $@"DapperMapper.Map: No Mapper found at store for property {kvp.Key.Name} of type {mType.ToString()}.
If you want to map a nested property you have to create a mapper for that property type.");

                    if (kvp.Key.MemberType == MemberTypes.Property)
                        ((PropertyInfo)kvp.Key).SetValue(mapped, nestedMapper.NoGenericMap(dapperResult, cleanResult));
                    else ((FieldInfo)kvp.Key).SetValue(mapped, nestedMapper.NoGenericMap(dapperResult, cleanResult));
                }
            }

            return mapped;
        }

The idea is to use:

MapperStore store = new MapperStore();
DapperMapper<Persons> mapper = (DapperMapper<Persons>)store.GetMapper(typeof(Persons));
Persons p = mapper.Map(dynamicDapperResult);

Due to it being generic and that the method has to recursively call other DapperMapper.Map methods, I use a non-generic interface to call the mappers while mapping at run time, using the NoGenericMap methods.
The generic DapperMapper<T> class actually maps the objects and is called at runtime. It uses the dictionaries to know if a member is nested or built-in, if it’s an interface, if it’s an IEnumerable or IDictionary, if it have to use a Func to create a member, etc. It actually does very little with reflection, the minimum I could manage to achieve.
Basically it first create an instance of the object (via reflection or with the configured constructor), then loops through all class members, search in the dictionaries for adequate type and member using the MemberTypeInfo Enum I spoke about above and fill the member according to what was configured following the priority showed in the diagram. If a member is a nested type, just create a new mapper and again and again.
IEnumerableand IDictionary members have a their own classes to map them, EnumerableMapper and DictionaryMapper. They simply create an instance of the adequate object and search the data to map all the collection members through the dynamic Dapper’s result, which will call again a normal DapperMapper if they are configured as nested types.

There’s an overloaded method to map enumerables:

public R Map<R>(IEnumerable<dynamic> dapperResult, string splitOn = "Id", bool cleanResult = false)
        where R : IEnumerable<T>

One must call this method if want to map a whole IEnumerable of objects:

List<Persons> myList = mapper.Map<List<Persons>>(dapperResult, "Id");

I didn’t find other way to do this except with an overloaded method.

In general the Dapper result dynamic members must have the same name as the object to be mapped members. I wrote the code to support prefixes and sufixes, that can be added via MapperConfig, and a parser to “decode” them at runtime.
The parser:

public class PrePostFixesParser
{
    public PrePostFixesParser(iDapperMapper mapper)
    {
        Tuple<string[], bool> prefixes = mapper != null ? mapper.Prefixes : null;
        Tuple<string[], bool> postfixes = mapper != null ? mapper.Postfixes : null;

        if (prefixes != null)
        {
            this.Prefixes = prefixes.Item1;
            this.PrefixesExclusive = prefixes.Item2;
            this.PrefixesCount = prefixes.Item1.Select(x => x.Count()).Distinct();
        }
        else
        {
            this.Prefixes = null;
            this.PrefixesExclusive = false;
            this.PrefixesCount = new int[] { 0 };
        }

        if (postfixes != null)
        {
            this.Postfixes = postfixes.Item1;
            this.PostfixesExclusive = postfixes.Item2;
            this.PostfixesCount = postfixes.Item1.Select(x => x.Count()).Distinct();
        }
    }

    #region properties
    public string[] Prefixes { get; private set; }
    public string[] Postfixes { get; private set; }
    public bool PrefixesExclusive { get; private set; }
    public bool PostfixesExclusive { get; private set; }
    public IEnumerable<int> PrefixesCount { get; private set; }
    public IEnumerable<int> PostfixesCount { get; private set; }
    #endregion

    #region helpers
    private bool RemovePrefixIfStringContains(ref string str)
    {
        if (Prefixes == null)
            return false;

        bool contain = false;
        foreach (int count in PrefixesCount)
        {
            //contains some of the configurated prefixes
            contain = Prefixes.Contains(str.Substring(0, count));
            if (contain)
            {
                str = str.Remove(0, count);
                return contain;
            }
        }

        return contain;
    }
    private bool RemovePostfixIfStringContains(ref string str)
    {
        if (Postfixes == null)//(PostfixesCount.Count() == 1 && PostfixesCount.First() == 0)
            return false;

        bool contain = false;
        foreach (int count in PostfixesCount)
        {
            contain = Postfixes.Contains(str.Substring(str.Length - count, count));
            if (contain)
            {
                str = str.Remove(str.Length - count, count);
                return contain;
            }
        }
        return contain;
    }
    private bool KeysContainsSomePrePostfix(IDictionary<string, object> dict)
    {
        if (Prefixes != null && Postfixes != null)
        {
            return dict.Any(kvp =>
            {
                foreach (int count in PrefixesCount)
                {
                    //contains some of the configurated prefixes or postfixes
                    if (Prefixes.Contains(kvp.Key.Substring(0, count))
                        || Postfixes.Contains(kvp.Key.Substring(kvp.Key.Length - count, count)))
                        return true;
                    else return false;
                }
                return false;
            });
        }
        else if (Prefixes != null)
        {
            return dict.Any(kvp =>
            {
                foreach (int count in PrefixesCount)
                {
                    //contains some of the configurated prefixes
                    if (Prefixes.Contains(kvp.Key.Substring(0, count)))
                        return true;
                    else return false;
                }
                return false;
            });
        }
        else if (Postfixes != null)
        {
            return dict.Any(kvp =>
            {
                foreach (int count in PrefixesCount)
                {
                    //contains some of the configurated postfixes
                    if (Postfixes.Contains(kvp.Key.Substring(kvp.Key.Length - count, count)))
                        return true;
                    else return false;
                }
                return false;
            });
        }
        return false;
        //return dict.Any(kvp => (Prefixes.Contains(kvp.Key.Substring(0,)
    }
    #endregion

    #region public methods
    public string RemoveFieldsUnderscore(string str)
    {
        if (str.StartsWith("_")) return str.Remove(0, 1);
        return str;
    }
    public IEnumerable<string> GetCleanNamesList(IEnumerable<string> namesList)
    {
        return namesList.Select(str => RemoveFieldsUnderscore(str));
    }
    public IEnumerable<IDictionary<string, object>> RemovePrePostFixesFromDictionary(IEnumerable<dynamic> dyn)
    {
        List<Dictionary<string, object>> ienum = new List<Dictionary<string, object>>();
        foreach (dynamic d in dyn)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            foreach (KeyValuePair<string, object> kvp in (d as IDictionary<string, object>))
            {
                string keyWithoutPrePostfixes = kvp.Key;
                if (!RemovePrefixIfStringContains(ref keyWithoutPrePostfixes) && !RemovePostfixIfStringContains(ref keyWithoutPrePostfixes))
                    dict.Add(kvp.Key, kvp.Value);
                else
                    dict.Add(keyWithoutPrePostfixes, kvp.Value);//return new KeyValuePair<string, object>(keyWithoutPrePostfixes, kvp.Value);
            }
            ienum.Add(dict);
        }

        return ienum;
    }
    public dynamic GetTypeMembersWithoutPrePostFixes(dynamic dyn, IEnumerable<string> namesList)
    {
        var typeMembers = new ExpandoObject() as IDictionary<string, object>;
        IDictionary<string, object> dict = dyn as IDictionary<string, object>;
        IEnumerable<string> names = namesList.Select(str => RemoveFieldsUnderscore(str));

        int i = 0;
        if (!PrefixesExclusive && !PostfixesExclusive)
        {
            foreach (KeyValuePair<string, object> kvp in dict)
            {
                string keyWithoutPrePostfixes = kvp.Key;
                bool namesContainsKey = names.Contains(kvp.Key);

                if (!RemovePrefixIfStringContains(ref keyWithoutPrePostfixes)
                    && !RemovePostfixIfStringContains(ref keyWithoutPrePostfixes)
                    && namesContainsKey)
                {
                    typeMembers.Add(kvp.Key, kvp.Value);
                    i++;
                }
                else if (names.Contains(keyWithoutPrePostfixes))
                {
                    typeMembers.Add(keyWithoutPrePostfixes, kvp.Value);
                    i++;
                }
            }
        }
        else if (PrefixesExclusive && PostfixesExclusive)
        {
            foreach (KeyValuePair<string, object> kvp in dict)
            {
                string keyWithoutPrePostfixes = kvp.Key;
                if (RemovePrefixIfStringContains(ref keyWithoutPrePostfixes)
                    && RemovePostfixIfStringContains(ref keyWithoutPrePostfixes)
                    && names.Contains(keyWithoutPrePostfixes))
                    typeMembers.Add(keyWithoutPrePostfixes, kvp.Value);
            }
        }
        else if (PrefixesExclusive)
        {
            foreach (KeyValuePair<string, object> kvp in dict)
            {
                string keyWithoutPrePostfixes = kvp.Key;
                if (RemovePrefixIfStringContains(ref keyWithoutPrePostfixes))
                {
                    RemovePostfixIfStringContains(ref keyWithoutPrePostfixes);

                    if (names.Contains(keyWithoutPrePostfixes))
                        typeMembers.Add(keyWithoutPrePostfixes, kvp.Value);
                }
            }
        }
        else
        {
            foreach (KeyValuePair<string, object> kvp in dict)
            {
                string keyWithoutPrePostfixes = kvp.Key;
                if (RemovePostfixIfStringContains(ref keyWithoutPrePostfixes))
                {
                    RemovePrefixIfStringContains(ref keyWithoutPrePostfixes);

                    if (names.Contains(keyWithoutPrePostfixes))
                        typeMembers.Add(keyWithoutPrePostfixes, kvp.Value);
                }
            }
        }

        return typeMembers;
    }
    #endregion
}

And that’s all, I think. If you are still reading this I believe I have to thank you and congratulate you πŸ˜›
Besides that, I’ll just post the test I did that I mentioned at the beginning (and the results with a simple object and with an object with dictionary members), and that will be all:

        public static void MapperTest<T>(int testsTotal, int desde, int cada, int idAlias = 0, bool deleteFirst = true)
        {
            Type t = typeof(T);
            string filepath = @"E:TESTMAPPER." + t.Name + ".xlsx";
            if (deleteFirst && File.Exists(filepath))
                File.Delete(filepath);

            var file = new FileInfo(filepath);
            var package = new ExcelPackage(file);
            ExcelWorksheet wSheet = package.Workbook.Worksheets.Add("prueba1");

            wSheet.Cells[1, 1].Value = $"MAPPERTEST:  MAP {t.Name} ; Tests: { testsTotal.ToString()}. Desde: { desde.ToString()}. Cada: { cada.ToString()}.";
            wSheet.Cells[2, 1].Value = "ID";
            wSheet.Cells[2, 2].Value = "TYPE";
            wSheet.Cells[2, 3].Value = "OBJECTS CREATED";
            wSheet.Cells[2, 4].Value = "SECONDS";
            wSheet.Cells[2, 5].Value = "MILISECONDS";
            wSheet.Cells[2, 6].Value = "SECONDS/OBJECTS";

            Console.WriteLine("MAPPERTEST:");
            Console.WriteLine($@"    1.- MAP {t.Name}
        tests: {testsTotal.ToString()}.
        desde: {desde.ToString()}.
        cada: {cada.ToString()}.");
            Console.WriteLine();
            Console.WriteLine("    -WAITING-");
            Console.ReadLine();
            Console.WriteLine("------------------");
            Console.WriteLine();

            for (int j = desde, x = 0; j < (testsTotal * cada); j += cada, x++)
            {
                Console.WriteLine("...");
                Console.WriteLine($"    Test NΒΊ {x.ToString()}.");
                Console.WriteLine($"    NΒΊ objetos a crear: {j.ToString()}");
                Console.WriteLine();
                Console.WriteLine("...");

                using (SqlConnection con = new SqlConnection(conString))//(MySqlConnection con = new MySqlConnection(conString))
                {
                    con.Open();
                    var result = con.Query(@"SELECT p.Id,p.Nombre,pif.pruebaI,pif.otro,a.Id aId,a.Acc aAcc,a.Persona aPersona 
FROM Persons p 
RIGHT JOIN Acc a ON p.Id=a.Persona 
RIGHT JOIN pruebaif pif ON p.Id=pif.Persona
WHERE p.Id=1");

                    Stopwatch watch = new Stopwatch();
                    watch.Reset();
                    watch.Start();

                    for (int i = 0; i < j; i++)
                    {
                        T p;
                        MapperStore store = new MapperStore();
                        DapperMapper<T> mapper = (DapperMapper<T>)store.GetMapper(t);
                        p = mapper.Map(result);
                    }

                    watch.Stop();
                    Console.WriteLine($"    +++++++++TEST {t.Name} - {x.ToString()} DONE+++++++++");
                    Console.WriteLine();
                    Console.WriteLine($"    TIME WATCH: {watch.Elapsed.ToString()}");
                    Console.WriteLine($"    TIME WATCH SECONDS: {watch.Elapsed.Seconds.ToString()}");
                    Console.WriteLine($"    TIME WATCH MILISECONDS: {watch.ElapsedMilliseconds.ToString()}");
                    Console.WriteLine();

                    wSheet.Cells[x + 2, 1].Value = x + idAlias;
                    wSheet.Cells[x + 2, 2].Value = t.Name;
                    wSheet.Cells[x + 2, 3].Value = j;
                    wSheet.Cells[x + 2, 4].Value = watch.Elapsed.Seconds;
                    wSheet.Cells[x + 2, 5].Value = watch.ElapsedMilliseconds;
                    wSheet.Cells[x + 2, 6].Formula = "D3/C3";

                    con.Close();
                }
                Console.WriteLine("------------------");
                Console.WriteLine("DB OK");
                Console.WriteLine();
            }

            package.Save();
            Console.WriteLine("    +++++++++ALL TESTS DONE+++++++++");
            Console.WriteLine();
            Console.ReadLine();
        }

PS.: There’s a SQL query builder in the same Github link that I made for the same project too, but that’s another story, it’s just string concatenations using some of the mapper dictionaries, just ignore it.

Edit:
Asked by @t3chb0t in the comments I’m putting an example of an object to be mapped:

public class Apunte : IObjModelBase, IOwnerComunidad, IObjWithDLO<ApunteDLO>
{
    public Apunte() { }
    public Apunte(int id, int idComunidad, Asiento asiento, string FacturaId = null)
    {
        this._Id = id;
        this._IdOwnerComunidad = idComunidad;
        this._Asiento = asiento;
        this._Factura = FacturaId;
    }

    #region fields
    private int _Id;
    private int _IdOwnerComunidad;
#pragma warning disable CS0649
    private int _OrdenEnAsiento;
#pragma warning restore CS0649
    private Asiento _Asiento;
    private DebitCredit _DebeHaber;
    private decimal _Importe;
    private string _Factura;
    #endregion

    #region properties
    public int Id { get { return this._Id; } }        
    public int IdOwnerComunidad { get { return this._IdOwnerComunidad; } }
    public int OrdenEnAsiento { get { return this._OrdenEnAsiento; } }
    public Asiento Asiento { get { return this._Asiento; } }
    public string Concepto { get; set; }        
    public DebitCredit DebeHaber
    {
        get { return this._DebeHaber; }
        set
        {
            if (this._DebeHaber != value)
            {                    
                if(!_Asiento.Abierto)
                    throw new CustomException_ObjModels(
                        $"Error cambiando DebeHaber de apunte numero {Id} de asiento numero {Asiento.Id}. Asiento cerrado.");
                this._Asiento.CambiaSaldo(this, value);
                this._DebeHaber = value;
            }
        }
    }        
    public decimal Importe
    {
        get { return this._Importe; }
        set
        {
            if (this._Importe != value)
            {
                if (!_Asiento.Abierto)
                    throw new CustomException_ObjModels(
                        $"Error cambiando DebeHaber de apunte numero {Id} de asiento numero {Asiento.Id}. Asiento cerrado.");
                this._Asiento.CambiaSaldo(this, value);
                this._Importe = value;
            }
        }
    }
    public CuentaMayor Cuenta { get; set; }
    public bool Punteo { get; set; }        
    public string Factura { get { return this._Factura; } }
    #endregion

    #region DLO
    public ApunteDLO GetDLO()
    {
        return new ApunteDLO(Id, IdOwnerComunidad, OrdenEnAsiento, Asiento.Codigo.CurrentCodigo, Concepto, DebeHaber, Importe, Cuenta.NumCuenta.ToString(),
            Punteo, Factura);
    }
    #endregion
}

It’s a model I use in the same project I did the mapper for. The database have all the plain data, at the beginning of the APP I configure the type (if you note it, it’s the same object I used as an example for the configuration), and the repository map the objects through this mapper when needed, again as I described before in the question.


Get this bounty!!!

#StackBounty: #c++ #network-programming #boost-asio #distributed-computing Mesh networking in boost.Asio

Bounty: 50

I’m trying to build mesh network in Boost.Asio where each node can talk with each other also to a master node where master sends instructions to different node like node A do this and ACK me, node B send data to C and ACK me.They should be also aware of who is who(nodes) and sends messages accordingly.

enter image description here

I am able to make server-single client synchronous system but unable to design and code above mentioned system with asio.
Needs guidance on this.

Any code sample would be highly thankful.
My network configuration is fixed. I do not have to worry about new nodes joining or leaving.


Get this bounty!!!

#StackBounty: #unity #c# #camera #gui Constraining camera bounds within bounds based on Unity UI object dimensions

Bounty: 50

I have a perspective camera which has bounds which I wish to constrain within larger bounds. All the bounds are calculated in world space.

The code for containing the camera within the constraining bounds is straightforward:

        var camRect = this.cameraComponent.GetCameraWorldRect();
        var correction = Vector3.zero;

        if (camRect.xMin < constrainingRect.xMin)
        {
            correction.x += Mathf.Abs(constrainingRect.xMin - camRect.xMin);
        }

        if (camRect.xMax > constrainingRect.xMax)
        {
            correction.x -= Mathf.Abs(constrainingRect.xMax - camRect.xMax);
        }

        if (camRect.yMin < constrainingRect.yMin)
        {
            correction.y += Mathf.Abs(constrainingRect.yMin - camRect.yMin);
        }

        if (camRect.yMax > constrainingRect.yMax)
        {
            correction.y -= Mathf.Abs(constrainingRect.yMax - camRect.yMax);
        }

        this.cameraComponent.transform.position += correction;

This can be visualized as:

Camera Constraints Without UI

The problem I am facing is that I have a UI object that is covering the right hand side of the screen and I am uncertain how to correctly calculate the width of the UI object so that the constrained camera bounds can take it into account.

Camera Constraints Including UI

The camera that is drawing the UI object is configured as follows:

UI Camera Configuration

The camera that is being constrained is configured as follows:

Constrained Camera Configuration

Apart from the layer, the parameters which affect the rendering of the objects for each camera configuration are the same.

The UI object has the following configuration with a Canvas Renderer:

UI Object Configuration

This is how I am currently attempting to calculate to width of the UI object but given that the UI is being rendered using a perspective camera I wasn’t too certain that ScreenToWorldPosition was correct.

    private float CalculateMenuWidth()
    {
        // Generate padding to account for the side menu
        var canvas = LevelEditor.Instance.Menu.GetComponentInParent<Canvas>();
        var menuRect = LevelEditor.Instance.Menu.GetComponent<RectTransform>();
        var menuRectMax = menuRect.rect.max * canvas.scaleFactor;
        var menuRectMin = menuRect.rect.min * canvas.scaleFactor;

        if (this.cameraComponent.orthographic)
        {
            return Mathf.Abs(this.cameraComponent.ScreenToWorldPoint(menuRectMax).x - this.cameraComponent.ScreenToWorldPoint(menuRectMin).x);
        }

        // Perspective camera requires distance for ScreenToWorldPoint
        var distance = Mathf.Abs(this.cameraComponent.transform.position.z);

        return Mathf.Abs(this.cameraComponent.ScreenToWorldPoint(new Vector3(menuRectMax.x, 0f, distance)).x - this.cameraComponent.ScreenToWorldPoint(new Vector3(menuRectMin.x, 0f, distance)).x);
    }

However, the size of menu returned by the method above appears to be too large.

How can I correctly calculate the width of the UI object so it appears that the camera constraints do not allow the camera to travel past the UI object?

EDIT: I’ve added a link to a Unity project which is the minimal working example for reproducing the issue.

https://www.dropbox.com/s/mq36mfqz5wvvsch/CameraConstraintGUIIssue.zip

The camera can be controlled with WASD to translate and the Shift key will speed up the movement.

The camera is constrained inside the checkerboard. An offset is created so that the camera should stop moving to the right once the right edge of the checkerboard is adjacent to the left edge of the menu. Unfortunately, I can’t seem to calculate the size of the menu correctly so this occurs.

The code for constraining the camera and calculating the menu size is in EditorCamera.cs.


Get this bounty!!!

#StackBounty: #c# #android #xamarin How to simulate screen touch on android with xamarin?

Bounty: 50

I am making an application for automating certain things, for example while having a 3rd party app open, my application, running in the background, would simulate a click on the screen, at given coordinates, which would look like a regular screen tap to the 3rd party app.

But I am stuck on the actual screen tap simulation, how can I achieve it with Xamarin for Android?

The app will have root privileges.

Thank you.


Get this bounty!!!

#StackBounty: #c# #rdlc #barcode #report-designer #ean-13 Visual Studio Report Designer: Embed font

Bounty: 500

I have some special font: EAN-13 and I need to insert a barcode into my report, so i have no idea how I can use embed font for that.

I can load my font in runtime:

    private static PrivateFontCollection Pfc;
    private static async Task<FontFamily> EAN13()
    {
        if (Pfc == null)
        {
            Pfc = new PrivateFontCollection();

            Stream fontStream = typeof(DefferedPurchase)
                .Assembly
                .GetManifestResourceStream("ActionsC.Resources.EAN-13.ttf");

            byte[] fontdata = new byte[fontStream.Length];
            await fontStream.ReadAsync(fontdata, 0, (int)fontStream.Length);
            fontStream.Close();
            unsafe
            {
                fixed (byte* pFontData = fontdata)
                {
                    Pfc.AddMemoryFont((IntPtr)pFontData, fontdata.Length);
                }
            }
        }
        return Pfc.Families.FirstOrDefault();
    }

But how i can apply it to this rdlc xml node?

      <Textbox Name="textbox19">
        <CanGrow>true</CanGrow>
        <ToggleImage>
          <InitialState>true</InitialState>
        </ToggleImage>
        <KeepTogether>true</KeepTogether>
        <Paragraphs>
          <Paragraph>
            <TextRuns>
              <TextRun>
                <Value>=Parameters!BarCode.Value</Value>
                <Style>
                  <FontFamily><!--     


                        see here       


                   --></FontFamily>
                  <FontSize>12pt</FontSize>
                </Style>
              </TextRun>
            </TextRuns>
            <Style />
          </Paragraph>
        </Paragraphs>
        <rd:DefaultName>textbox1</rd:DefaultName>
        <Top>13.4995cm</Top>
        <Left>21.53213cm</Left>
        <Height>3.10467cm</Height>
        <Width>5.6385cm</Width>
        <ZIndex>30</ZIndex>
        <Style>
          <PaddingLeft>2pt</PaddingLeft>
          <PaddingRight>2pt</PaddingRight>
          <PaddingTop>2pt</PaddingTop>
          <PaddingBottom>2pt</PaddingBottom>
        </Style>
      </Textbox>

Any ideas?

Opened font window:
enter image description here


Get this bounty!!!

#StackBounty: #c# #mono #nancy Nancy does not render the view nor extending the layout view

Bounty: 100

I started learning about C# in Mono (Ubuntu) and Nancy which is a web framework for C#. I am using their “super simple view engine” rendering and I cannot make the code to render the .sshtml file, it just shows as plan text file. Ultimately, I want to use a layout file (layout.sshtml) and each view would replace part of layout file.

I have a hunch that maybe folder structure is not valid and for example login.sshtml does not find the layout.sshtml. But I modified the .csproj file to copy Views folders:

  <Target Name="AfterBuild" Condition=" '$(Configuration)' == 'Debug' ">
    <!-- needed to deply views folder -->
    <Exec Command="cp -a  Views $(OutDir)" />
    <!-- needed to deply database if not newer -->
    <Exec Command="cp -a -u  Database/db.sqlite $(OutDir)" />
  </Target>

I am just confused on why it does not render the view. Any help would be appreciated.

This is the link to my repository

This is folder structure of my project:

β”œβ”€β”€ bin
β”‚Β Β  └── Debug
β”‚Β Β      β”œβ”€β”€ csharp-practice.exe
β”‚Β Β      β”œβ”€β”€ csharp-practice.exe.mdb
β”‚Β Β      β”œβ”€β”€ db.sqlite
β”‚Β Β      β”œβ”€β”€ Nancy.dll
β”‚Β Β      β”œβ”€β”€ Nancy.Hosting.Self.dll
β”‚Β Β      β”œβ”€β”€ nancy-simple-app.exe
β”‚Β Β      β”œβ”€β”€ nancy-simple-app.exe.mdb
β”‚Β Β      └── Views
β”‚Β Β          β”œβ”€β”€ index.sshtml
β”‚Β Β          β”œβ”€β”€ layout.sshtml
β”‚Β Β          β”œβ”€β”€ login.sshtml
β”‚Β Β          └── register.sshtml
β”œβ”€β”€ Database
β”‚Β Β  β”œβ”€β”€ DataBaseManager.cs
β”‚Β Β  └── db.sqlite
β”œβ”€β”€ LICENSE
β”œβ”€β”€ nancy-simple-app.csproj
β”œβ”€β”€ nancy-simple-app.sln
β”œβ”€β”€ nancy-simple-app.userprefs
β”œβ”€β”€ obj
β”‚Β Β  └── x86
β”‚Β Β      └── Debug
β”‚Β Β          β”œβ”€β”€ csharp-practice.csproj.FilesWrittenAbsolute.txt
β”‚Β Β          β”œβ”€β”€ csharp-practice.exe
β”‚Β Β          β”œβ”€β”€ csharp-practice.exe.mdb
β”‚Β Β          β”œβ”€β”€ nancy-simple-app.csproj.FilesWrittenAbsolute.txt
β”‚Β Β          β”œβ”€β”€ nancy-simple-app.exe
β”‚Β Β          └── nancy-simple-app.exe.mdb
β”œβ”€β”€ packages
β”‚Β Β  β”œβ”€β”€ Nancy.1.4.3
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ lib
β”‚Β Β  β”‚Β Β  β”‚Β Β  └── net40
β”‚Β Β  β”‚Β Β  β”‚Β Β      β”œβ”€β”€ Nancy.dll
β”‚Β Β  β”‚Β Β  β”‚Β Β      └── Nancy.xml
β”‚Β Β  β”‚Β Β  └── Nancy.1.4.3.nupkg
β”‚Β Β  β”œβ”€β”€ Nancy.Hosting.Self.1.4.1
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ lib
β”‚Β Β  β”‚Β Β  β”‚Β Β  └── net40
β”‚Β Β  β”‚Β Β  β”‚Β Β      β”œβ”€β”€ Nancy.Hosting.Self.dll
β”‚Β Β  β”‚Β Β  β”‚Β Β      └── Nancy.Hosting.Self.xml
β”‚Β Β  β”‚Β Β  └── Nancy.Hosting.Self.1.4.1.nupkg
β”‚Β Β  └── repositories.config
β”œβ”€β”€ packages.config
β”œβ”€β”€ Program.cs
β”œβ”€β”€ Properties
β”‚Β Β  └── AssemblyInfo.cs
β”œβ”€β”€ ViewModels
β”‚Β Β  └── UserModel.cs
└── Views
    β”œβ”€β”€ index.sshtml
    β”œβ”€β”€ layout.sshtml
    β”œβ”€β”€ login.sshtml
    └── register.sshtml

Screenshot:

enter image description here


Get this bounty!!!

#StackBounty: #c# #visual-studio-2015 #garbage-collection #garbage Viewing garbage collection history in c# (VS2015)

Bounty: 50

A unforeseen and unanticipated amount of garbage collection activity is shown in the ‘Process Memory’ graph when I run my application which makes me want to know where in the program is the garbage generated as I don’t feel that I have any memory leaks in the program. Can someone please tell me if there is a way to view the parts (or lines) of my code where garbage is generated?

Thanks in advance.


Get this bounty!!!

#StackBounty: #c# Using Boyer–Moore algorithms in 64 bit processes

Bounty: 50

Im in the process of making an memory scanner app similar to cheat engine, but would like to do it in c#, as an test project…
so, i was using a lib that makes use of https://github.com/Adversities/Cheatool
which uses Boyer–Moore.

the process detection is working..and in 32 bit processes i can find Array of bytes like `

60 8A DD 01 48 00 00 BC 88 01 04 02 00 01 44 D0 30 60 8C DD 01 46 AD
1F 00 2A 12 10 00 00 29

` correctly if i look for them using the Boyer–Moore method…

but for some reason i cant find them in 64 bit processes.

how can i update the methods found in the dll lib and my app to accommodate 64 bit processes as well?
now, as im quite new to c#, and like experimenting, i drafted an test app:

code of Testing application:

   using System;
using System.Diagnostics;

using System.Linq;

using System.Threading.Tasks;
using System.Collections.Generic;
using System.Runtime.InteropServices;


using System.Threading;

namespace MemTester
{





    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "Memory Addres Tester [?] (PID: ?)";

            //Console.Write("Process to open => ");
            //string process = Console.ReadLine();
            string process = " ";
            int ppid = 0;
            while (ppid == 0)
            {
                Console.Write("Process PID to open as int=> ");
                string ppid2 = Console.ReadLine();
                if ((ppid2 == "") || (ppid2 == null) || (ppid2.Length < 2))
                { ppid2 = "0"; }
                ppid = Convert.ToInt32(ppid2);
            }
            while (true)
            {
                Console.Write("Value to scan => ");
                string aob = Console.ReadLine();
                if (aob == "exit") break;

                MeMory(process, aob, ppid);
            }
        }
        public abstract class Manager
        {
            [DllImport("KERNEL32.DLL", SetLastError = true)]
            public static extern bool WriteProcessMemory(
                IntPtr process, IntPtr address, byte[] buffer, uint size, ref uint written);

            [DllImport("KERNEL32.DLL")]
            public static extern bool VirtualProtectEx(IntPtr process, IntPtr address,
                uint size, uint access, out uint oldProtect);

            [DllImport("KERNEL32.DLL")]
            public static extern int CloseHandle(IntPtr objectHandle);

            [DllImport("KERNEL32.DLL")]
            public static extern IntPtr OpenProcess(uint access, bool inheritHandler, uint processId);

            [Flags]
            public enum Protection
            {
                PEReadWrite = 0x40,
                PReadWrite = 0x04
            }

            [Flags]
            public enum Access
            {
                Synchronize = 0x100000,
                StandardRightsRequired = 0x000F0000,
                AllAccess = StandardRightsRequired | Synchronize | 0xFFFF
            }
        }
        public abstract class Reader
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct MEMORY_BASIC_INFORMATION
            {
                public IntPtr BaseAddress;
                public IntPtr AllocationBase;
                public uint AllocationProtect;
                public uint RegionSize;
                public uint State;
                public uint Protect;
                public uint Type;
            }

            [DllImport("KERNEL32.DLL")]
            public static extern int VirtualQueryEx(IntPtr hProcess,
                IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);

            [DllImport("KERNEL32.DLL", SetLastError = true)]
            public static extern bool ReadProcessMemory(
                IntPtr process, IntPtr address, byte[] buffer, uint size, ref uint read);

            public List<MEMORY_BASIC_INFORMATION> MemoryRegion = new List<MEMORY_BASIC_INFORMATION>();
        }
        public class BoyerMoore : Reader
        {
            private IntPtr _processHandle;

            public BoyerMoore(IntPtr processHandle)
            {
                _processHandle = processHandle;
            }

            private void MemInfo(bool unwritable)
            {
                IntPtr Addy = new IntPtr();

                while (true)
                {
                    MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION();

                    int MemDump = VirtualQueryEx(_processHandle, Addy, out memInfo, Marshal.SizeOf(memInfo));

                    if (MemDump == 0) break;

                    if ((memInfo.State & 0x1000) != 0)
                    {
                        if (unwritable && (memInfo.Protect & 0xCC) != 0)
                            MemoryRegion.Add(memInfo);
                        else
                            MemoryRegion.Add(memInfo);
                    }

                    Addy = new IntPtr(memInfo.BaseAddress.ToInt32() + (int)memInfo.RegionSize);
                }
            }

            private void BoyerAlgo(IntPtr baseAddress, byte[] memoryBrick, byte[] pattern, ref List<IntPtr> addresses)
            {
                int offSet = 0;
                while ((offSet = Array.IndexOf(memoryBrick, pattern[0], offSet)) != -1)
                {
                    if (pattern.Length > 1)
                        for (int i = 1; i < pattern.Length; i++)
                        {
                            if (memoryBrick.Length <= offSet + pattern.Length
                                || pattern[i] != memoryBrick[offSet + i]) break;

                            if (i == pattern.Length - 1)
                                addresses.Add(new IntPtr((int)baseAddress + offSet));
                        }
                    else addresses.Add(new IntPtr((int)baseAddress + offSet));
                    offSet++;
                }
            }

            private void BoyerAlgo(IntPtr baseAddress, byte[] memoryBrick, string pattern, ref List<IntPtr> addresses)
            {
                int offSet = 0;
                string[] aob = pattern.Split(' ');
                List<int> bytesPos = new List<int>();

                for (int i = 0; i < aob.Length; i++)
                    if (aob[i] != "??")
                        bytesPos.Add(i);

                if (bytesPos.Count != 0)
                    while ((offSet = Array.IndexOf(memoryBrick, (byte)Convert.ToInt32(aob[bytesPos[0]], 16), offSet)) != -1)
                    {
                        if (bytesPos.Count > 1)
                            for (int i = 1; i < bytesPos.Count; i++)
                            {
                                if (memoryBrick.Length <= offSet + pattern.Length
                                    || (byte)Convert.ToInt32(aob[bytesPos[i]], 16)
                                    != memoryBrick[(offSet - bytesPos[0]) + bytesPos[i]]) break;

                                if (i == bytesPos.Count - 1)
                                    if (aob[0] == "??")
                                        addresses.Add(new IntPtr((int)baseAddress + (offSet - bytesPos[0])));
                                    else addresses.Add(new IntPtr((int)baseAddress + offSet));
                            }
                        else
                            addresses.Add(new IntPtr((int)baseAddress + (offSet - bytesPos[0])));
                        offSet++;
                    }
                else
                    for (int i = 0; i < memoryBrick.Length; i++)
                        addresses.Add(new IntPtr((int)baseAddress + i));
            }

            public CancellationTokenSource cancelToken { get; set; } = new CancellationTokenSource();

            public Task<IntPtr[]> AoByte(string pattern, bool unwritable = false)
            {
                if (!pattern.Contains("?"))
                {
                    byte[] buff = pattern.Split(' ').Select(by =>
                    (byte)Convert.ToInt32(by, 16)).ToArray();

                    return Task.Run(() => { return GeneralScan(buff, unwritable); }, cancelToken.Token);
                }
                else return Task.Run(() => { return WCScan(pattern, unwritable); }, cancelToken.Token);
            }


            private IntPtr[] GeneralScan(byte[] buff, bool unwritable)
            {
                MemInfo(unwritable);

                List<IntPtr> addresses = new List<IntPtr>();

                for (int i = 0; i < MemoryRegion.Count; i++)
                {
                    uint read = 0;
                    byte[] wholeMemory = new byte[MemoryRegion[i].RegionSize];

                    ReadProcessMemory(_processHandle, MemoryRegion[i].BaseAddress, wholeMemory,
                        MemoryRegion[i].RegionSize, ref read);

                    BoyerAlgo(MemoryRegion[i].BaseAddress, wholeMemory, buff, ref addresses);
                }
                return addresses.ToArray();
            }

            private IntPtr[] WCScan(string pattern, bool unwritable)
            {
                MemInfo(unwritable);

                List<IntPtr> addresses = new List<IntPtr>();

                for (int i = 0; i < MemoryRegion.Count; i++)
                {
                    uint read = 0;
                    byte[] wholeMemory = new byte[MemoryRegion[i].RegionSize];

                    ReadProcessMemory(_processHandle, MemoryRegion[i].BaseAddress, wholeMemory,
                        MemoryRegion[i].RegionSize, ref read);

                    BoyerAlgo(MemoryRegion[i].BaseAddress, wholeMemory, pattern, ref addresses);
                }
                return addresses.ToArray();
            }
        }

        public class MeMorybox : Manager
        {

            public BoyerMoore BoyerScan { get; set; }


            IntPtr _processHandle;

            public MeMorybox(Process process)
            {
                _processHandle = OpenProcess((uint)Access.AllAccess, false, (uint)process.Id);


                BoyerScan = new BoyerMoore(_processHandle);

            }



            ~MeMorybox()
            {
                CloseHandle(_processHandle);
            }

        }

        static void MeMory(string process, string aob, int ppid)
        {
            //Process[] processList = Process.GetProcessesByName(process);
            Process p = Process.GetProcessById(ppid); ;

            MeMorybox notepad = new MeMorybox(p);

            Console.WriteLine("Hex value of pid:"+p.Id.ToString("x8"));

            var addresses = notepad.BoyerScan.AoByte(aob).GetAwaiter().GetResult();

        Console.WriteLine(addresses.Length + " hits found for pid:"+ppid);

        Console.WriteLine();
    }
}

testing for flash process..
firefox..<32 bit process>
chrome..<64 bit process>
url to test: https://apps.facebook.com/candycrushsoda

array of byte to search as test:60 ?? ?? ?? ?? ?? ?? ?? ?? 01 ?? ?? 00 01 44 ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 2A 12 10 00 00 29

it should give 1 result

in firefox–Flashplayerplugin it works fine,

in chrome–one of the processes containing module pepflashplayer.dll it >gives no result, as chrome is a 64 bit process.

To verify i double checked by using cheatengine, in both cases the aob is found correctly


Get this bounty!!!

#StackBounty: #c# #angular #asp.net-core #asp.net-core-webapi #angular-universal Server side rendering. Web API and Angular 2

Bounty: 150

I’ve developed an web application built using ASP.NET Core Web API and Angular 4. My module bundler is Web Pack 2.

I would like to make my application to be crawlable or link sharable by Facebook, Twitter, Google. The url must be the same when some user tries to post my news at Facebook. For example, Jon wants to share a page with url – http://myappl.com/#/hellopage at Facebook, then Jon inserts this link into Facebook: http://myappl.com/#/hello.

I’ve seen this tutorial of Angular Universal server side rendering without tag helper and would like to make server side rendering. As I use ASP.NET Core Web API and my Angular 4 application does not have any .cshtml views, so I cannot send data from controller to view through ViewData["SpaHtml"] from my controller:

`ViewData["SpaHtml"] = prerenderResult.Html; ` 

In addition, I see this google tutorial of Angular Universal, but they use NodeJS server, not ASP.NET Core.

I would like to use server side prerendering. I am adding metatagsthrough this way:

`import { Meta } from '@angular/platform-browser';

constructor(
    private metaService: Meta) {
}

let newText = "Foo data. This is test data!:)";
    //metatags to publish this page at social nets
    this.metaService.addTags([
        // Open Graph data
        { property: 'og:title', content: newText },
        { property: 'og:description', content: newText },        { 
        { property: "og:url", content: window.location.href },        
        { property: 'og:image', content: "http://www.freeimageslive.co.uk/files
                                /images004/Italy_Venice_Canal_Grande.jpg" }]);`

and when I inspect this element in a browser it looks like this:

<head>    
    <meta property="og:title" content="Foo data. This is test data!:)">    
    <meta property="og:description" content="Foo data. This is test data!:)">
    <meta name="og:url" content="http://foourl.com">
    <meta property="og:image" content="http://www.freeimageslive.co.uk/files
/images004/Italy_Venice_Canal_Grande.jpg"">    
</head>

I am bootstrapping the application usual way:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

and my webpack.config.js config looks like this:

var path = require('path');

var webpack = require('webpack');

var ProvidePlugin = require('webpack/lib/ProvidePlugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var WebpackNotifierPlugin = require('webpack-notifier');

var isProd = (process.env.NODE_ENV === 'production');

function getPlugins() {
    var plugins = [];

    // Always expose NODE_ENV to webpack, you can now use `process.env.NODE_ENV`
    // inside your code for any environment checks; UglifyJS will automatically
    // drop any unreachable code.
    plugins.push(new webpack.DefinePlugin({
        'process.env': {
            'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
        }
    }));

    plugins.push(new webpack.ProvidePlugin({
        jQuery: 'jquery',
        $: 'jquery',
        jquery: 'jquery'
    }));
    plugins.push(new CleanWebpackPlugin(
        [
            './wwwroot/js',
            './wwwroot/fonts',
            './wwwroot/assets'
        ]
    ));

    return plugins;
}


module.exports = {

    devtool: 'source-map',

    entry: {
        app: './persons-app/main.ts' // 
    },

    output: {
        path: "./wwwroot/",
        filename: 'js/[name]-[hash:8].bundle.js',
        publicPath: "/"
    },

    resolve: {
        extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html']
    },

    devServer: {
        historyApiFallback: true,
        stats: 'minimal',
        outputPath: path.join(__dirname, 'wwwroot/')
    },

    module: {
        rules: [{
                test: /.ts$/,
                exclude: /node_modules/,
                loader: 'tslint-loader',
                enforce: 'pre'
            },
            {
                test: /.ts$/,
                loaders: [
                    'awesome-typescript-loader',
                    'angular2-template-loader',

                    'angular-router-loader',

                    'source-map-loader'
                ]
            },
            {
                test: /.js/,
                loader: 'babel',
                exclude: /(node_modules|bower_components)/
            },
            {
                test: /.(png|jpg|gif|ico)$/,
                exclude: /node_modules/,
                loader: "file?name=img/[name].[ext]"
            },
            {
                test: /.css$/,
                exclude: /node_modules/,                
                use: ['to-string-loader', 'style-loader', 'css-loader'],
            },
            {
                test: /.scss$/,
                exclude: /node_modules/,
                loaders: ["style", "css", "sass"]
            },
            {
                test: /.html$/,
                loader: 'raw'
            },
            {
                test: /.(eot|svg|ttf|woff|woff2|otf)$/,
                loader: 'file?name=fonts/[name].[ext]'
            }
        ],
        exprContextCritical: false
    },
    plugins: getPlugins()

};

Is it possible to do server side rendering without ViewData? Is there an alternative way to make server side rendering in ASP.NET Core Web API and Angular 2?

I have uploaded an example to a github repository.


Get this bounty!!!

#StackBounty: #c++ #macros #m4 Autotools detect C++ language standard support

Bounty: 100

I have been updating my build tools to optionally use autotools (autoconfig/automake/libtool etc.).

As part of this change I have written a couple of M4 macros. This not being something I have done before. Any input is appreciated on style or if things can be done better.

A macro for detecting what version of C++ is available and defining the correct flags:

AC_DEFUN(
    [AX_FUNC_THOR_LANG_FLAG],
    [
        minLangFeature=$1
        AS_IF([test "$2" = ""], [maxLangFeature=17], [maxLangFeature=$2])
        AS_IF([test $minLangFeature -gt $maxLangFeature], AC_MSG_ERROR([Invalid Language Value],[1]))

        AC_LANG(C++)
        CXXMaxLanguage=03
        CXXExpLanguage=03
        AX_CHECK_COMPILE_FLAG([-std=c++11], [AC_SUBST([CXXMaxLanguage],11) AC_SUBST([StdFlag11],[-std=c++11])])
        AX_CHECK_COMPILE_FLAG([-std=c++14], [AC_SUBST([CXXMaxLanguage],14) AC_SUBST([StdFlag14],[-std=c++14])])
        AX_CHECK_COMPILE_FLAG([-std=c++17], [AC_SUBST([CXXMaxLanguage],17) AC_SUBST([StdFlag17],[-std=c++17])])
        AX_CHECK_COMPILE_FLAG([-std=c++1x], [AC_SUBST([CXXExpLanguage],11) AC_SUBST([ExpFlag11],[-std=c++1x])])
        AX_CHECK_COMPILE_FLAG([-std=c++1y], [AC_SUBST([CXXExpLanguage],14) AC_SUBST([ExpFlag14],[-std=c++1y])])
        AX_CHECK_COMPILE_FLAG([-std=c++1z], [AC_SUBST([CXXExpLanguage],17) AC_SUBST([ExpFlag17],[-std=c++1z])])

        #CXX_STD_FLAG
        #CXXSTDVER

        AS_IF(
            [test $minLangFeature -le $CXXMaxLanguage],
            [
                AS_IF(
                    [test $maxLangFeature -le $CXXMaxLanguage],
                    [AC_SUBST([CXXSTDVER], [$maxLangFeature])],
                    [AC_SUBST([CXXSTDVER], [$CXXMaxLanguage])]
                )
                AC_SUBST([CXX_STD_FLAG], [$(eval echo "${StdFlag${CXXSTDVER}}")])
                ],
                [AS_IF(
                    [test $minLangFeature -le $CXXExpLanguage],
                    [
                        AS_IF(
                            [test $maxLangFeature -le $CXXExpLanguage],
                            [AC_SUBST([CXXSTDVER], [$maxLangFeature])],
                            [AC_SUBST([CXXSTDVER], [$CXXExpLanguage])]
                        )
                        AC_SUBST([CXX_STD_FLAG], [$(eval echo "${ExpFlag${CXXSTDVER}}")])
                ],
                [AC_MSG_ERROR([

Error: Need C++${minLangFeature} but the compiler only supports ${CXXMaxLanguage} (Experimental ${CXXExpLanguage})

                    ], [1])]
            )]
        )
    ]
)

Usage:

AX_FUNC_THOR_LANG_FLAG(<min acceptable C++> [, <max acceptable C++>])

If you don’t specify a max then 17 is used as the default. It works out what flags are available to modify the behavior of the C++ compiler to a different version of the standard and then defines the two macros:

CXXSTDVER      /* Will hold 03 11 14 or 17 */
CXX_STD_FLAG   /* Will hold the flag needed be the C++ compiler */

It considers -std=c++1[147] as standard version and will use these if they satisfy the minimum requirements. It considers -std=c++1[xyz] as experimental versions and will only use these if the minimum requirements cannot be achieved by using the standard version flags.


Get this bounty!!!