internal static Func CreateTransform()

in Source/Tx.Network/Snmp/Dynamic/TrapTypeMap.cs [56:168]


        internal static Func<SnmpDatagram, object> CreateTransform(Type outputTrapType)
        {
            var parameter = Expression.Parameter(typeof(SnmpDatagram), "snmpDatagram");
            var receivedTimestampProperty = typeof (SnmpDatagram).GetProperty("ReceivedTime",
                BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);

            var pduVarBindsField = typeof(SnmpDatagram).GetProperty(
                "VarBinds",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
            var sourceAddressProperty = typeof(SnmpDatagram).GetProperty(
                "SourceIpAddress",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

            var varbindVar = Expression.Variable(typeof(VarBind), "varBind");
            var varbindValueField = typeof(VarBind).GetField("Value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

            var getVarBindMethod = typeof(VarBindExtensions).GetMethod("SearchFirstSubOidWith");
            var bindings = new List<MemberBinding>();

            MemberAssignment notificationObjectsExpression = null, ipAddressExpresion = null, timestampExpression = null;
            foreach (var p in outputTrapType.GetProperties())
            {
                var notificationObjectIdentifier =
                    p.GetCustomAttributes(typeof(SnmpOidAttribute), false).OfType<SnmpOidAttribute>().FirstOrDefault();
                if (notificationObjectIdentifier == null)
                {
                    var notificationObjects =
                        p.GetCustomAttributes(typeof(NotificationObjectsAttribute), false)
                            .OfType<NotificationObjectsAttribute>()
                            .FirstOrDefault();
                    if (notificationObjects != null && p.PropertyType.IsAssignableFrom(pduVarBindsField.PropertyType))
                    {
                        notificationObjectsExpression = Expression.Bind(p, Expression.Property(parameter, pduVarBindsField));
                    }

                    var ipAddressAttribute =
                    p.GetCustomAttributes(typeof(IpAddressAttribute), false)
                        .OfType<IpAddressAttribute>()
                        .FirstOrDefault();
                    if (ipAddressAttribute != null)
                    {
                        Expression ipAddress = Expression.Property(parameter, sourceAddressProperty);
                        if (p.PropertyType == typeof(IPAddress))
                        {
                            ipAddress = Expression.Call(typeof(IPAddress).GetMethod("Parse"), ipAddress); 
                        }
                        ipAddressExpresion = Expression.Bind(p, ipAddress);
                    }

                    var timestampAttribute = p.GetCustomAttributes(typeof(TimestampAttribute), false)
                        .OfType<TimestampAttribute>()
                        .FirstOrDefault();
                    if (timestampAttribute != null && p.PropertyType.IsAssignableFrom(receivedTimestampProperty.PropertyType))
                    {
                        Expression timestamp = Expression.Property(parameter, receivedTimestampProperty);
                        timestampExpression = Expression.Bind(p, timestamp);
                    }

                    continue;
                }

                var foundValue = Expression.Call(getVarBindMethod, Expression.Property(parameter, pduVarBindsField), Expression.Constant(notificationObjectIdentifier.Oid), varbindVar);

                Expression convertedValue = Expression.Field(varbindVar, varbindValueField);
                if (p.PropertyType.IsEnum || typeof(int).IsAssignableFrom(p.PropertyType))
                {
                    convertedValue = Expression.Convert(convertedValue, typeof(long));
                }
                else if (p.PropertyType == typeof(byte[]))
                {
                    convertedValue = Expression.Call(
                        typeof(TrapTypeMap).GetMethod(
                            "GetRawOctetStringBytes",
                            BindingFlags.Static | BindingFlags.NonPublic), Expression.Convert(convertedValue, typeof(string)));
                }

                var conditional = Expression.Condition(
                    foundValue, 
                    Expression.Convert(convertedValue, p.PropertyType),
                    Expression.Default(p.PropertyType));

                var b = Expression.Bind(p, conditional);
                bindings.Add(b);
            }

            if (notificationObjectsExpression != null)
            {
                bindings.Add(notificationObjectsExpression);
            }

            if (ipAddressExpresion != null)
            {
                bindings.Add(ipAddressExpresion);
            }

            if (timestampExpression != null)
            {
                bindings.Add(timestampExpression);
            }

            var newExpression = Expression.New(outputTrapType);
            var memberInitialization = Expression.MemberInit(newExpression, bindings.ToArray());
            var castToObject = Expression.Convert(memberInitialization, typeof(object));

            var nullCheck = Expression.Condition(
                Expression.Equal(Expression.Constant(null, typeof(SnmpDatagram)), parameter),
                Expression.Constant(null, typeof(object)), castToObject);

            var codeBlock = Expression.Block(new[] { varbindVar, }, nullCheck);
            var transformExpression = Expression.Lambda<Func<SnmpDatagram, object>>(codeBlock, parameter);

            return transformExpression.Compile();
        }