Наследование: IComparer, IEqualityComparer, IComparer, IEqualityComparer
Пример #1
0
        /// <summary>
        /// Initialize the list of root folders.
        /// </summary>
        private void InitializeFolders(Guid parentId)
        {
            lock (DataModel.SyncRoot)
            {
                LambdaComparer <FolderTreeNode> folderTreeNodeComparer = new LambdaComparer <FolderTreeNode>((l, r) => l.Entity.Name.CompareTo(r.Entity.Name));
                List <FolderTreeNode>           folders = new List <FolderTreeNode>();
                EntityRow parentEntityRow = DataModel.Entity.EntityKey.Find(parentId);

                foreach (EntityTreeRow entityTreeRow in parentEntityRow.GetEntityTreeRowsByFK_Entity_EntityTree_ParentId())
                {
                    FolderTreeNode folderTreeNode = new FolderTreeNode()
                    {
                        Entity = new Entity(entityTreeRow.EntityRowByFK_Entity_EntityTree_ChildId)
                    };
                    Int32 index = folders.BinarySearch(folderTreeNode, folderTreeNodeComparer);

                    if (index < 0)
                    {
                        index = ~index;
                    }

                    folders.Insert(index, folderTreeNode);
                }

                this.Dispatcher.BeginInvoke(new Action(() => this.Folders = folders), DispatcherPriority.Normal);
            }
        }
Пример #2
0
        /// <summary>
        /// Initialize the list of root folders.
        /// </summary>
        private void InitializeFolders()
        {
            lock (DataModel.SyncRoot)
            {
                LambdaComparer <FolderTreeNode> folderTreeNodeComparer = new LambdaComparer <FolderTreeNode>((l, r) => l.Entity.Name.CompareTo(r.Entity.Name));
                List <FolderTreeNode>           folders = new List <FolderTreeNode>();
                EntityRow userEntityRow = DataModel.Entity.EntityKey.Find(UserContext.Instance.UserId);

                foreach (EntityTreeRow entityTreeRow in userEntityRow.GetEntityTreeRowsByFK_Entity_EntityTree_ParentId())
                {
                    FolderTreeNode folderTreeNode = new FolderTreeNode(entityTreeRow);
                    Int32          index          = folders.BinarySearch(folderTreeNode, folderTreeNodeComparer);

                    if (index < 0)
                    {
                        index = ~index;
                    }

                    folders.Insert(index, folderTreeNode);
                }

                this.Dispatcher.BeginInvoke(new Action(delegate()
                {
                    this.Folders = folders;
                    this.ExpandFolder();
                }), DispatcherPriority.Normal);
            }
        }
Пример #3
0
        static IList <GameObject> SortByX(GameObject[] os)
        {
            var objects = new SortedList <Vector3, GameObject>(LambdaComparer.Create((Vector3 a, Vector3 b) => {
                if (a.y < b.y)
                {
                    return(-1);
                }
                if (a.y == b.y && a.x < b.x)
                {
                    return(-1);
                }
                if (a.y == b.y && a.x == b.x)
                {
                    return(0);
                }
                return(1);
            }));

            foreach (var o in Selection.gameObjects)
            {
                objects.Add(o.transform.localPosition, o);
            }

            return(objects.Values);
        }
Пример #4
0
        public void Classes_with_single_non_equal_compared_value_are_different()
        {
            _right.IntegerValue = -1;

            var comparer = new LambdaComparer<ClassWithProperties>(x => x.IntegerValue);

            Assert.IsFalse(comparer.Equals(_left, _right));
        }
Пример #5
0
        public void Classes_with_multiple_compared_values_for_which_only_the_first_is_equal_are_different()
        {
            _right.StringValue = null;

            var comparer = new LambdaComparer<ClassWithProperties>(x => x.IntegerValue, x => x.StringValue);

            Assert.IsFalse(comparer.Equals(_left, _right));
        }
Пример #6
0
            public void TestDistincUntilChanged()
            {
                var nums = new[] { 1, 1, 2, 2, 3, 3 };

                nums
                .DistinctUntilChanged(LambdaComparer.Factory <int>((i1, i2) => i1 == i2))
                .Do(Console.WriteLine)
                .Count();
            }
Пример #7
0
 public static void sort <T_Type>(
     T_Type[] inoutArray, int inStartIndex, int inLength,
     System.Func <T_Type, T_Type, Comparation> inLambda)
 {
     XUtils.check(null != inLambda);
     System.Array.Sort(inoutArray, inStartIndex, inLength,
                       LambdaComparer <T_Type> .getForLambda(inLambda)
                       );
 }
Пример #8
0
        public void Classes_with_single_compared_null_value_are_equal()
        {
            _right.StringValue = null;
            _left.StringValue = null;

            var comparer = new LambdaComparer<ClassWithProperties>(x => x.StringValue);

            Assert.IsTrue(comparer.Equals(_left, _right));
        }
Пример #9
0
        public static void AreEqual <T>(this Assert assert, T expected, T actual, CompareFunc <T> compareFunc)
        {
            var comparer = new LambdaComparer <T>(compareFunc);

            CollectionAssert.AreEqual(
                new[] { expected },
                new[] { actual }, comparer,
                $"\nExpected: <{expected}>.\nActual: <{actual}>.");
        }
Пример #10
0
 static void FileMatch1(int count)
 {
     var comparer = new LambdaComparer<Item>((x,y)=>x.Name == y.Name);
     using (var traker = new TimeTick(string.Format("Test1 - Using Intersect ", count, count * 3)))
     {
         var items = LeftItems.Intersect(RightItems, comparer);
         traker.Stop(items.Count());
     }
 }
        public void hashCode_should_be_the_func_result()
        {
            var compare = new LambdaComparer <Person>((x, y) => x.firstname == y.firstname, z => z.age.GetHashCode());
            var p       = new Person {
                age = 1
            };

            Console.WriteLine(compare.GetHashCode(p));
            Assert.Equal(p.age.GetHashCode(), compare.GetHashCode(p));
        }
Пример #12
0
        public float time(float d)
        {
            int i = Array.BinarySearch(this.d, Tuple.Create(0f, d)
                                       , LambdaComparer.Create((Tuple <float, float> a, Tuple <float, float> b) => Comparer <float> .Default.Compare(a.Item2, b.Item2)));

            if (i >= 0)
            {
                return(this.d[i].Item1);
            }

            i = -i - 1;
            return(d.InvLerp(this.d[i - 1].Item2, this.d[i].Item2).Lerp(this.d[i - 1].Item1, this.d[i].Item1));
        }
Пример #13
0
        public float distance(float t)
        {
            int i = Array.BinarySearch(d, Tuple.Create(t, 0f)
                                       , LambdaComparer.Create((Tuple <float, float> a, Tuple <float, float> b) => Comparer <float> .Default.Compare(a.Item1, b.Item1)));

            if (i >= 0)
            {
                return(d[i].Item2);
            }

            i = -i - 1;
            return(t.InvLerp(d[i - 1].Item1, d[i].Item1).Lerp(d[i - 1].Item2, d[i].Item2));
        }
        public void Equals_given_same_reference_returns_True()
        {
            // arrange
            object object1 = new object();
            object object2 = object1;

            IEqualityComparer<object> comparer = new LambdaComparer<object>((x, y) => x.Equals(y));

            // act
            bool equals = comparer.Equals(object1, object2);

            // assert
            Assert.IsTrue(equals);
        }
        public void Equals_given_true_predicate_returns_True()
        {
            // arrange
            DateTime dateTime1 = DateTime.Today;
            DateTime dateTime2 = DateTime.Today;

            IEqualityComparer<DateTime> comparer = new LambdaComparer<DateTime>((x, y) => x.Equals(y));

            // act
            bool equals = comparer.Equals(dateTime1, dateTime2);

            // assert
            Assert.IsTrue(equals);
        }
        public void Equals_given_false_predicate_returns_False()
        {
            // arrange
            DateTime dateTime1 = DateTime.MinValue;
            DateTime dateTime2 = DateTime.MaxValue;

            IEqualityComparer<DateTime> comparer = new LambdaComparer<DateTime>((x, y) => x.Equals(y));

            // act
            bool equals = comparer.Equals(dateTime1, dateTime2);

            // assert
            Assert.IsFalse(equals);
        }
Пример #17
0
        public void TransferToDifferentPQTest()
        {
            var q1 = new PriorityQueueExtended <CPersonWithIndex>(sm_peopleWithIndex);
            var q2 = new PriorityQueueOptimized <CPersonWithIndex>(q1, LambdaComparer <CPersonWithIndex> .FromFunc((_l, _r) => _r.Age - _l.Age));

            var arr1 = q1.ToArray();
            var arr2 = q2.ToArray();

            Assert.AreEqual(arr1.Length, arr2.Length, "Array lengths aren't equal");

            for (var i = 0; i < arr1.Length; i++)
            {
                var j = arr1.Length - i - 1;
                Assert.AreEqual(arr1[i], arr2[j], "The objects are not equal at index " + i + " / " + j);
            }
        }
Пример #18
0
        /// <summary>
        ///     Sorts the source collection using custom sort criteria.
        /// </summary>
        /// <remarks>
        ///     Please note that your compare function needs to take care about
        ///     proper conversion of types to be comparable!
        /// </remarks>
        /// <param name="source">
        ///     The source collection to sort.
        /// </param>
        /// <param name="args">
        ///     Sort criteria to use.
        /// </param>
        /// <returns>
        ///     A sorted array containing collection elements.
        /// </returns>
        public object Execute(ICollection source, object[] args)
        {
            if (source == null || source.Count == 0)
            {
                return(source);
            }

            if (args == null || args.Length != 1)
            {
                throw new ArgumentException("compare expression is a required argument for orderBy");
            }

            var       arg      = args[0];
            IComparer comparer = null;

            if (arg is string)
            {
                var expCompare = Expression.Parse((string)arg);
                comparer = new SimpleExpressionComparer(expCompare);
            }
            else if (arg is IComparer)
            {
                comparer = (IComparer)arg;
            }
            else if (arg is LambdaExpressionNode)
            {
                var fnCompare = (LambdaExpressionNode)arg;
                if (fnCompare.ArgumentNames.Length != 2)
                {
                    throw new ArgumentException("compare function must accept 2 arguments");
                }
                comparer = new LambdaComparer(fnCompare);
            }
            else if (arg is Delegate)
            {
                comparer = new DelegateComparer((Delegate)arg);
            }

            AssertUtils.ArgumentNotNull(comparer, "comparer",
                                        "orderBy(comparer) argument 'comparer' does not evaluate to a supported type");

            var list = new ArrayList(source);

            list.Sort(comparer);
            return(list);
        }
Пример #19
0
        /// <summary>
        ///     Sorts the source collection using custom sort criteria.
        /// </summary>
        /// <remarks>
        ///     Please note that your compare function needs to take care about
        ///     proper conversion of types to be comparable!
        /// </remarks>
        /// <param name="source">
        ///     The source collection to sort.
        /// </param>
        /// <param name="args">
        ///     Sort criteria to use.
        /// </param>
        /// <returns>
        ///     A sorted array containing collection elements.
        /// </returns>
        public object Execute(ICollection source, object[] args)
        {
            if (source == null || source.Count == 0)
            {
                return source;
            }

            if (args == null || args.Length != 1)
            {
                throw new ArgumentException("compare expression is a required argument for orderBy");
            }

            var arg = args[0];
            IComparer comparer = null;
            if (arg is string)
            {
                var expCompare = Expression.Parse((string) arg);
                comparer = new SimpleExpressionComparer(expCompare);
            }
            else if (arg is IComparer)
            {
                comparer = (IComparer) arg;
            }
            else if (arg is LambdaExpressionNode)
            {
                var fnCompare = (LambdaExpressionNode) arg;
                if (fnCompare.ArgumentNames.Length != 2)
                {
                    throw new ArgumentException("compare function must accept 2 arguments");
                }
                comparer = new LambdaComparer(fnCompare);
            }
            else if (arg is Delegate)
            {
                comparer = new DelegateComparer((Delegate) arg);
            }

            AssertUtils.ArgumentNotNull(comparer, "comparer",
                "orderBy(comparer) argument 'comparer' does not evaluate to a supported type");

            var list = new ArrayList(source);
            list.Sort(comparer);
            return list;
        }
Пример #20
0
        /// <summary>
        /// Initialize the list of root folders.
        /// </summary>
        private void InitializeFolders()
        {
            lock (DataModel.SyncRoot)
            {
                LambdaComparer <FolderTreeNode> folderTreeNodeComparer = new LambdaComparer <FolderTreeNode>((l, r) => l.Entity.Name.CompareTo(r.Entity.Name));
                List <FolderTreeNode>           folders = new List <FolderTreeNode>();
                var entities = DataModel.Entity.Where(row =>
                                                      (row.GetFolderRows().Length > 0 || row.GetBlotterRows().Length > 0));

                foreach (EntityRow entityRow in entities)
                {
                    Boolean topLevel = true;

                    // Determine whether a folder/blotter has any parent folders or blotters.
                    foreach (EntityTreeRow entityTreeRow in entityRow.GetEntityTreeRowsByFK_Entity_EntityTree_ChildId())
                    {
                        EntityRow parent = entityTreeRow.EntityRowByFK_Entity_EntityTree_ParentId;

                        if (parent.GetFolderRows().Length > 0 || parent.GetBlotterRows().Length > 0)
                        {
                            topLevel = false;
                            break;
                        }
                    }

                    // If they don't add them to our list.
                    if (topLevel)
                    {
                        FolderTreeNode folderTreeNode = new FolderTreeNode(entityRow);
                        Int32          index          = folders.BinarySearch(folderTreeNode, folderTreeNodeComparer);

                        if (index < 0)
                        {
                            index = ~index;
                        }

                        folders.Insert(index, folderTreeNode);
                    }
                }

                this.Dispatcher.BeginInvoke(new Action(() => this.Folders = folders), DispatcherPriority.Normal);
            }
        }
Пример #21
0
        /// <summary>
        /// Working job
        /// </summary>
        /// <param name="sender">Object</param>
        /// <param name="e">Argument to the work (none there)</param>
        private void Bw_DoWork(object sender, DoWorkEventArgs e)
        {
            ReportProgress(0, null);

            NDSAdvanScene xmlAvant = new NDSAdvanScene();

            xmlAvant.Load(_xmlAvant);
            NDSAdvanScene xmlApres = new NDSAdvanScene();

            xmlApres.Load(_xmlApres);

            ReportProgress(0, "Calculating Differences ...");

            IEqualityComparer <NDS_Rom> comparerCRC = new LambdaComparer <NDS_Rom>(
                (o, n) =>
                o.RomCRC == n.RomCRC);
            List <NDS_Rom> diffAll = xmlApres.DataBase.Except(xmlAvant.DataBase, comparerCRC).ToList();

            ReportProgress(45, string.Format("Found {0} differences", diffAll.Count));

            IEqualityComparer <NDS_Rom> comparerRomNumber = new LambdaComparer <NDS_Rom>(
                (o, n) =>
                o.ReleaseNumber == n.ReleaseNumber);
            List <NDS_Rom> diffNew = xmlApres.DataBase.Except(xmlAvant.DataBase, comparerRomNumber).ToList();

            ReportProgress(90, string.Format("Found {0} new Roms", diffNew.Count));

            List <NDS_Rom> diffModified = diffAll.Except(diffNew).ToList();

            ReportProgress(100, string.Format("Found {0} modified Roms", diffModified.Count));

            for (int i = 0; i < diffNew.Count; i++)
            {
                ReportProgress((i + 1) * 100 / diffAll.Count, string.Format("New Rom : {0}", diffNew[i].Title));
            }

            for (int i = 0; i < diffModified.Count; i++)
            {
                ReportProgress((i + 1 + diffNew.Count) * 100 / diffAll.Count, string.Format("Modified Rom : {0}", diffModified[i].Title));
            }
        }
Пример #22
0
        // ---------------------- Lists

        /// <summary>
        /// Sorts the elements of a sequence in ascending order according to a key.
        /// Unlike standard Linq NOT a stable sort.
        /// </summary>
        /// <param name="source">A sequence of values to order.</param>
        /// <param name="keySelector">A function to extract a key from an element.</param>
        /// <param name="comparer">A Comparer to compare keys.</param>
        /// <returns>A sequence whose elements are ordered according to a key</returns>
        public static List <TSource> OrderByF <TSource, TKey>(this List <TSource> source, Func <TSource, TKey> keySelector, IComparer <TKey> comparer = null)
        {
            if (source == null)
            {
                throw Error.ArgumentNull(nameof(source));
            }

            if (keySelector == null)
            {
                throw Error.ArgumentNull("keySelector");
            }

            if (comparer == null)
            {
                comparer = Comparer <TKey> .Default;
            }

            List <TSource> result = new List <TSource>(source);
            LambdaComparer <TSource, TKey> lambdaComparer = new LambdaComparer <TSource, TKey>(keySelector, comparer);

            result.Sort(lambdaComparer);
            return(result);
        }
Пример #23
0
    public ArbitrarySortedDictionary(Func <TVALUE, TSORT> sortFunc)
    {
        _SortFunc = sortFunc;
        Func <SortedDictionaryKey, SortedDictionaryKey, Int32> compFunc = (x, y) => {
            Int32 sortValComp = 0;
            if (x.SortVal != null)
            {
                sortValComp = x.SortVal.CompareTo(y.SortVal);
            }
            if (sortValComp != 0)
            {
                return(sortValComp);
            }
            if (x.Key != null)
            {
                return(x.Key.CompareTo(y.Key));
            }
            return(y.Key == null ? 0 : -1);
        };
        var comparer = new LambdaComparer <SortedDictionaryKey>(compFunc);

        _SortedKeys   = new SortedList <SortedDictionaryKey, TKEY>(comparer);
        _SortedValues = new SortedList <SortedDictionaryKey, TVALUE>(comparer);
    }
        private static bool CheckDuplicates(ListBox ItemsBox, LambdaComparer comparer)
        {
            for (int i = 0; i < ItemsBox.Items.Count; i++)
            {
                object item = ItemsBox.Items[i];
                if (comparer( (item as ListBoxItem).Tag )) // for certain data formats we must do equal not eq
                {
                    if (i != 0)
                    {
                        ItemsBox.Items.RemoveAt(i);
                        ItemsBox.Items.Insert(0, item);
                    }
                    return true;
                }
            }

            return false;
        }
Пример #25
0
 public virtual IEnumerable<Bed> GetUnassignedBeds(IEnumerable<Bed> beds)
 {
     var comparer = new LambdaComparer<Bed>((first, second) => first.Code == second.Code);
     return beds.Except(AssignedBeds, comparer);
 }
Пример #26
0
        public void Exception_is_thrown_if_no_value_getters_are_specified()
        {
            var comparer = new LambdaComparer<ClassWithProperties>();

            comparer.Equals(_left, _right);
        }
Пример #27
0
        /// <summary>
        /// Send email(s) over SendGrid’s v3 Web API.
        /// </summary>
        /// <param name="personalizations">The personalizations.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="contents">The contents.</param>
        /// <param name="from">From.</param>
        /// <param name="replyTo">The reply to.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="templateId">The template identifier.</param>
        /// <param name="sections">The sections.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="ipPoolName">Name of the ip pool.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="trackingSettings">The tracking settings.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>
        /// The message id.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">Too many recipients.</exception>
        /// <exception cref="Exception">Email exceeds the size limit.</exception>
        public async Task <string> SendAsync(
            IEnumerable <MailPersonalization> personalizations,
            string subject,
            IEnumerable <MailContent> contents,
            MailAddress from,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            string templateId = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            TrackingSettings trackingSettings   = null,
            CancellationToken cancellationToken = default)
        {
            if (personalizations == null || !personalizations.Any())
            {
                throw new ArgumentNullException(nameof(personalizations));
            }

            // This comparer is used to perform case-insensitive comparisons of email addresses
            var emailAddressComparer = new LambdaComparer <MailAddress>((address1, address2) => address1.Email.Equals(address2.Email, StringComparison.OrdinalIgnoreCase));

            // It's important to make a copy of the personalizations to ensure we don't modify the original array
            var personalizationsCopy = personalizations.Where(p => p != null).ToArray();

            foreach (var personalization in personalizationsCopy)
            {
                // Avoid duplicate addresses. This is important because SendGrid does not throw any
                // exception when a recipient is duplicated (which gives you the impression the email
                // was sent) but it does not actually send the email
                personalization.To = personalization.To?
                                     .Distinct(emailAddressComparer)
                                     .ToArray();
                personalization.Cc = personalization.Cc?
                                     .Distinct(emailAddressComparer)
                                     .Except(personalization.To, emailAddressComparer)
                                     .ToArray();
                personalization.Bcc = personalization.Bcc?
                                      .Distinct(emailAddressComparer)
                                      .Except(personalization.To, emailAddressComparer)
                                      .Except(personalization.Cc, emailAddressComparer)
                                      .ToArray();

                // SendGrid doesn't like empty arrays
                if (!(personalization.To?.Any() ?? true))
                {
                    personalization.To = null;
                }
                if (!(personalization.Cc?.Any() ?? true))
                {
                    personalization.Cc = null;
                }
                if (!(personalization.Bcc?.Any() ?? true))
                {
                    personalization.Bcc = null;
                }

                // Surround recipient names with double-quotes if necessary
                personalization.To  = EnsureRecipientsNamesAreQuoted(personalization.To);
                personalization.Cc  = EnsureRecipientsNamesAreQuoted(personalization.Cc);
                personalization.Bcc = EnsureRecipientsNamesAreQuoted(personalization.Bcc);
            }

            // The total number of recipients must be less than 1000. This includes all recipients defined within the to, cc, and bcc parameters, across each object that you include in the personalizations array.
            var numberOfRecipients = personalizationsCopy.Sum(p => p.To?.Count(r => r != null) ?? 0);

            numberOfRecipients += personalizationsCopy.Sum(p => p.Cc?.Count(r => r != null) ?? 0);
            numberOfRecipients += personalizationsCopy.Sum(p => p.Bcc?.Count(r => r != null) ?? 0);
            if (numberOfRecipients >= 1000)
            {
                throw new ArgumentOutOfRangeException("The total number of recipients must be less than 1000");
            }

            // SendGrid throws an unhelpful error when the Bcc email address is an empty string
            if (mailSettings?.Bcc != null && string.IsNullOrWhiteSpace(mailSettings.Bcc.EmailAddress))
            {
                mailSettings.Bcc.EmailAddress = null;
            }

            var isDynamicTemplate        = Template.IsDynamic(templateId);
            var personalizationConverter = new MailPersonalizationConverter(isDynamicTemplate);

            var data = new JObject();

            data.AddPropertyIfValue("from", from);
            data.AddPropertyIfValue("reply_to", replyTo);
            data.AddPropertyIfValue("subject", subject);
            data.AddPropertyIfValue("content", contents);
            data.AddPropertyIfValue("attachments", attachments);
            data.AddPropertyIfValue("template_id", templateId);
            data.AddPropertyIfValue("categories", categories);
            data.AddPropertyIfValue("send_at", sendAt?.ToUnixTime());
            data.AddPropertyIfValue("batch_id", batchId);
            data.AddPropertyIfValue("asm", unsubscribeOptions);
            data.AddPropertyIfValue("ip_pool_name", ipPoolName);
            data.AddPropertyIfValue("mail_settings", mailSettings);
            data.AddPropertyIfValue("tracking_settings", trackingSettings);
            data.AddPropertyIfValue("personalizations", personalizationsCopy, personalizationConverter);

            if (sections != null && sections.Any())
            {
                var sctns = new JObject();
                foreach (var section in sections)
                {
                    sctns.Add(section.Key, section.Value);
                }

                data.Add("sections", sctns);
            }

            if (headers != null && headers.Any())
            {
                var hdrs = new JObject();
                foreach (var header in headers)
                {
                    hdrs.Add(header.Key, header.Value);
                }

                data.Add("headers", hdrs);
            }

            if (customArgs != null && customArgs.Any())
            {
                var args = new JObject();
                foreach (var customArg in customArgs)
                {
                    args.Add(customArg.Key, customArg.Value);
                }

                data.Add("custom_args", args);
            }

            // Sendgrid does not allow emails that exceed 30MB
            var contentSize = JsonConvert.SerializeObject(data, Formatting.None).Length;

            if (contentSize > MAX_EMAIL_SIZE)
            {
                throw new Exception("Email exceeds the size limit");
            }

            var response = await _client
                           .PostAsync($"{_endpoint}/send")
                           .WithJsonBody(data)
                           .WithCancellationToken(cancellationToken)
                           .AsResponse()
                           .ConfigureAwait(false);

            if (response.Message.Headers.TryGetValues("X-Message-Id", out IEnumerable <string> values))
            {
                return(values?.FirstOrDefault());
            }

            return(null);
        }
Пример #28
0
        public void Computed_values_can_be_used_for_comparison()
        {
            _left.StringValue = "ABC";
            _right.StringValue = "abc";
            _left.IntegerValue = 1;
            _right.IntegerValue = 2;

            var comparer = new LambdaComparer<ClassWithProperties>(
                x => x.IntegerValue > 0, 
                x => x.StringValue.ToLower(), 
                x => x.StringValue.ToUpper() + x.IntegerValue / x.IntegerValue,
                x => true);

            Assert.IsTrue(comparer.Equals(_left, _right));
        }
Пример #29
0
        /// <summary>
        /// Send email(s) over SendGrid’s v3 Web API.
        /// </summary>
        /// <param name="personalizations">The personalizations.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="contents">The contents.</param>
        /// <param name="from">From.</param>
        /// <param name="replyTo">The reply-to addresses.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="templateId">The template identifier.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="ipPoolName">Name of the ip pool.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="trackingSettings">The tracking settings.</param>
        /// <param name="priority">The priority.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>
        /// The message id.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">Too many recipients.</exception>
        /// <exception cref="Exception">Email exceeds the size limit.</exception>
        public async Task <string> SendAsync(
            IEnumerable <MailPersonalization> personalizations,
            string subject,
            IEnumerable <MailContent> contents,
            MailAddress from,
            IEnumerable <MailAddress> replyTo    = null,
            IEnumerable <Attachment> attachments = null,
            string templateId = null,
            IEnumerable <KeyValuePair <string, string> > headers = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            TrackingSettings trackingSettings   = null,
            MailPriority priority               = MailPriority.Normal,
            CancellationToken cancellationToken = default)
        {
            if (_client?.BaseClient?.DefaultRequestHeaders?.Authorization?.Scheme?.Equals("Basic", StringComparison.OrdinalIgnoreCase) ?? false)
            {
                const string errorMessage  = "SendGrid does not support Basic authentication when sending transactional emails.";
                const string diagnosticLog = "This request was not dispatched to SendGrid because the exception returned by their API in this scenario is not clear: 'Permission denied, wrong credentials'.";
                throw new SendGridException(errorMessage, null, diagnosticLog);
            }

            if (personalizations == null || !personalizations.Any())
            {
                throw new ArgumentNullException(nameof(personalizations));
            }

            // This comparer is used to perform case-insensitive comparisons of email addresses
            var emailAddressComparer = new LambdaComparer <MailAddress>((address1, address2) => address1.Email.Equals(address2.Email, StringComparison.OrdinalIgnoreCase));

            // It's important to make a copy of the personalizations to ensure we don't modify the original array
            var personalizationsCopy = personalizations.Where(p => p != null).ToArray();

            foreach (var personalization in personalizationsCopy)
            {
                // Make sure the arrays are not null otherwise Linq's 'Except' method will throw a ArgumentNull exception (See GH-286).
                if (personalization.To == null)
                {
                    personalization.To = Array.Empty <MailAddress>();
                }
                if (personalization.Cc == null)
                {
                    personalization.Cc = Array.Empty <MailAddress>();
                }
                if (personalization.Bcc == null)
                {
                    personalization.Bcc = Array.Empty <MailAddress>();
                }

                // Avoid duplicate addresses. This is important because SendGrid does not throw any
                // exception when a recipient is duplicated (which gives you the impression the email
                // was sent) but it does not actually send the email
                personalization.To = personalization.To
                                     .Distinct(emailAddressComparer)
                                     .ToArray();
                personalization.Cc = personalization.Cc
                                     .Distinct(emailAddressComparer)
                                     .Except(personalization.To, emailAddressComparer)
                                     .ToArray();
                personalization.Bcc = personalization.Bcc
                                      .Distinct(emailAddressComparer)
                                      .Except(personalization.To, emailAddressComparer)
                                      .Except(personalization.Cc, emailAddressComparer)
                                      .ToArray();

                // SendGrid doesn't like empty arrays
                if (!personalization.To.Any())
                {
                    personalization.To = null;
                }
                if (!personalization.Cc.Any())
                {
                    personalization.Cc = null;
                }
                if (!personalization.Bcc.Any())
                {
                    personalization.Bcc = null;
                }

                // Surround recipient names with double-quotes if necessary
                personalization.To  = EnsureRecipientsNamesAreQuoted(personalization.To);
                personalization.Cc  = EnsureRecipientsNamesAreQuoted(personalization.Cc);
                personalization.Bcc = EnsureRecipientsNamesAreQuoted(personalization.Bcc);

                // Indicate if a dynamic template is being used. This is used by MailPersonalizationConverter to generate the appropriate JSON
                personalization.IsUsedWithDynamicTemplate = Template.IsDynamic(templateId);
            }

            // The total number of recipients must be less than 1000. This includes all recipients defined within the to, cc, and bcc parameters, across each object that you include in the personalizations array.
            var numberOfRecipients = personalizationsCopy.Sum(p => p.To?.Count(r => r != null) ?? 0);

            numberOfRecipients += personalizationsCopy.Sum(p => p.Cc?.Count(r => r != null) ?? 0);
            numberOfRecipients += personalizationsCopy.Sum(p => p.Bcc?.Count(r => r != null) ?? 0);
            if (numberOfRecipients >= 1000)
            {
                throw new ArgumentOutOfRangeException(nameof(numberOfRecipients), numberOfRecipients, "The total number of recipients must be less than 1000");
            }

            // Get the priority headers
            if (!_priorityHeaders.TryGetValue(priority, out KeyValuePair <string, string>[] priorityHeaders))
            {
                throw new Exception($"{priority} is an unknown priority");
            }

            // Combine headers with priority headers making sure not to duplicate priority headers
            var combinedHeaders = (headers ?? Array.Empty <KeyValuePair <string, string> >())
                                  .Where(kvp => !priorityHeaders.Any(p => p.Key.Equals(kvp.Key, StringComparison.OrdinalIgnoreCase)))
                                  .Concat(priorityHeaders);

            // Remove duplicates from the list of 'reply-to' addresses
            var cleanReplyTo = replyTo?.Distinct(emailAddressComparer) ?? Enumerable.Empty <MailAddress>();

            // SendGrid allows no more than 1000 'reply-to' addresses
            var numberOfReplyToAddresses = cleanReplyTo.Count();

            if (numberOfReplyToAddresses > 1000)
            {
                throw new ArgumentOutOfRangeException(nameof(numberOfReplyToAddresses), numberOfReplyToAddresses, "The number of distinct reply-to addresses can't exceed 1000");
            }

            // Serialize the mail message
            var data = new StrongGridJsonObject();

            data.AddProperty("from", from);
            data.AddProperty("reply_to_list", cleanReplyTo);
            data.AddProperty("subject", subject);
            data.AddProperty("content", contents);
            data.AddProperty("attachments", attachments);
            data.AddProperty("template_id", templateId);
            data.AddProperty("categories", categories);
            data.AddProperty("send_at", sendAt?.ToUnixTime());
            data.AddProperty("batch_id", batchId);
            data.AddProperty("asm", unsubscribeOptions);
            data.AddProperty("ip_pool_name", ipPoolName);
            data.AddProperty("mail_settings", mailSettings);
            data.AddProperty("tracking_settings", trackingSettings);
            data.AddProperty("personalizations", personalizationsCopy);
            data.AddProperty("headers", ConvertEnumerationToJson(combinedHeaders));
            data.AddProperty("custom_args", ConvertEnumerationToJson(customArgs));

            // SendGrid does not allow emails that exceed 30MB
            var serializedContent = JsonSerializer.Serialize(data, typeof(StrongGridJsonObject), JsonFormatter.SerializationContext);

            if (serializedContent.Length > MAX_EMAIL_SIZE)
            {
                throw new Exception("Email exceeds the size limit");
            }

            // Send the request
            var response = await _client
                           .PostAsync($"{_endpoint}/send")
                           .WithJsonBody(data)
                           .WithCancellationToken(cancellationToken)
                           .AsResponse()
                           .ConfigureAwait(false);

            // Get the messageId from the response
            return(response.Message.Headers.GetValue("X-Message-Id"));
        }
Пример #30
0
        public virtual IEnumerable <Bed> GetUnassignedBeds(IEnumerable <Bed> beds)
        {
            var comparer = new LambdaComparer <Bed>((first, second) => first.Code == second.Code);

            return(beds.Except(AssignedBeds, comparer));
        }
Пример #31
0
        private void ExtractBasicBlocksOfMethod(MethodReference method_reference)
        {
            MethodReference original_method_reference = method_reference;

            _methods_done.Add(original_method_reference.FullName);

            //          MethodReference new_method_reference = original_method_reference.SubstituteMethod2();
            //          method_reference = new_method_reference != null ? new_method_reference : original_method_reference;

            MethodDefinition method_definition = method_reference.Resolve();

            if (method_definition == null || method_definition.Body == null)
            {
                return;
            }
            int         change_set        = Cfg.StartChangeSet();
            int         instruction_count = method_definition.Body.Instructions.Count;
            List <INST> split_point       = new List <INST>();

            CFG.Vertex basic_block = (CFG.Vertex)Cfg.AddVertex(new CFG.Vertex()
            {
                Name = Cfg.NewNodeNumber().ToString()
            });
            basic_block._method_definition = method_definition;
            basic_block._method_reference  = original_method_reference;
            basic_block.Entry = basic_block;
            basic_block.Exit  = basic_block;
            basic_block.Entry.BlocksOfMethod = new List <CFG.Vertex>();
            basic_block.Entry.BlocksOfMethod.Add(basic_block);
            Cfg.Entries.Add(basic_block);

            // Add instructions to the basic block, including debugging information.
            // First, get debugging information on line/column/offset in method.
            if (!original_method_reference.Module.HasSymbols)
            {
                // Try to get symbols, but if none available, don't worry about it.
                try { original_method_reference.Module.ReadSymbols(); } catch { }
            }
            var symbol_reader            = original_method_reference.Module.SymbolReader;
            var method_debug_information = symbol_reader?.Read(method_definition);
            Collection <SequencePoint> sequence_points = method_debug_information != null ? method_debug_information.SequencePoints : new Collection <SequencePoint>();

            Mono.Cecil.Cil.MethodBody body = method_definition.Body;
            if (body == null)
            {
                throw new Exception("Body null, not expecting it to be.");
            }
            if (body.Instructions == null)
            {
                throw new Exception("Body has instructions collection.");
            }
            if (body.Instructions.Count == 0)
            {
                throw new Exception("Body instruction count is zero.");
            }
            SequencePoint previous_sp = null;

            for (int j = 0; j < instruction_count; ++j)
            {
                Mono.Cecil.Cil.Instruction instruction = body.Instructions[j];
                SequencePoint sp = sequence_points.Where(s => { return(s.Offset == instruction.Offset); }).FirstOrDefault();
                if (sp == null)
                {
                    sp = previous_sp;
                }
                INST wrapped_instruction = INST.Wrap(instruction, basic_block, sp);
                basic_block.Instructions.Add(wrapped_instruction);
                if (sp != null)
                {
                    previous_sp = sp;
                }
            }

            var instructions_before_splits = basic_block.Instructions.ToList();

            // Accumulate targets of jumps. These are split points for block "v".
            // Accumalated splits are in "leader_list" following this for-loop.
            for (int j = 0; j < instruction_count; ++j)
            {
                INST wrapped_instruction                = basic_block.Instructions[j];
                Mono.Cecil.Cil.OpCode      opcode       = wrapped_instruction.OpCode;
                Mono.Cecil.Cil.FlowControl flow_control = opcode.FlowControl;

                switch (flow_control)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                {
                    object operand = wrapped_instruction.Operand;
                    // Two cases of branches:
                    // 1) operand is a single instruction;
                    // 2) operand is an array of instructions via a switch instruction.
                    // In doing this type casting, the resulting instructions are turned
                    // into def's, and operands no longer correspond to what was in the original
                    // method. We override the List<> compare to correct this problem.
                    Mono.Cecil.Cil.Instruction   single_instruction    = operand as Mono.Cecil.Cil.Instruction;
                    Mono.Cecil.Cil.Instruction[] array_of_instructions = operand as Mono.Cecil.Cil.Instruction[];
                    if (single_instruction != null)
                    {
                        INST sp = null;
                        for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                        {
                            if (basic_block.Instructions[i].Offset == single_instruction.Offset &&
                                basic_block.Instructions[i].OpCode == single_instruction.OpCode)
                            {
                                sp = basic_block.Instructions[i];
                                break;
                            }
                        }
                        if (sp == null)
                        {
                            throw new Exception("Instruction go to not found.");
                        }
                        bool found = false;
                        foreach (INST split in split_point)
                        {
                            if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                            {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            split_point.Add(sp);
                        }
                    }
                    else if (array_of_instructions != null)
                    {
                        foreach (var ins in array_of_instructions)
                        {
                            Debug.Assert(ins != null);
                            INST sp = null;
                            for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                            {
                                if (basic_block.Instructions[i].Offset == ins.Offset &&
                                    basic_block.Instructions[i].OpCode == ins.OpCode)
                                {
                                    sp = basic_block.Instructions[i];
                                    break;
                                }
                            }
                            if (sp == null)
                            {
                                throw new Exception("Instruction go to not found.");
                            }
                            bool found = false;
                            foreach (INST split in split_point)
                            {
                                if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                                {
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                split_point.Add(sp);
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for basic block partitioning.");
                    }
                }
                break;
                }

                // Split blocks after certain instructions, too.
                switch (flow_control)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Call:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                case Mono.Cecil.Cil.FlowControl.Return:
                case Mono.Cecil.Cil.FlowControl.Throw:
                {
                    if (flow_control == Mono.Cecil.Cil.FlowControl.Call && !Campy.Utils.Options.IsOn("split_at_calls"))
                    {
                        break;
                    }
                    if (j + 1 < instruction_count)
                    {
                        var  ins = basic_block.Instructions[j + 1].Instruction;
                        INST sp  = null;
                        for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                        {
                            if (basic_block.Instructions[i].Offset == ins.Offset &&
                                basic_block.Instructions[i].OpCode == ins.OpCode)
                            {
                                sp = basic_block.Instructions[i];
                                break;
                            }
                        }
                        if (sp == null)
                        {
                            throw new Exception("Instruction go to not found.");
                        }
                        bool found = false;
                        foreach (INST split in split_point)
                        {
                            if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                            {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            split_point.Add(sp);
                        }
                    }
                }
                break;
                }
            }

            // Get try-catch blocks and add those split points.
            foreach (var eh in body.ExceptionHandlers)
            {
                var start = eh.TryStart;
                var end   = eh.TryEnd;
                // Split at try start.
                Instruction ins = start;
                INST        sp  = null;
                for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                {
                    if (basic_block.Instructions[i].Offset == ins.Offset &&
                        basic_block.Instructions[i].OpCode == ins.OpCode)
                    {
                        sp = basic_block.Instructions[i];
                        break;
                    }
                }
                if (sp == null)
                {
                    throw new Exception("Instruction go to not found.");
                }
                bool found = false;
                foreach (INST split in split_point)
                {
                    if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    split_point.Add(sp);
                }
            }

            // Note, we assume that these splits are within the same method.
            // Order the list according to offset from beginning of the method.
            List <INST> ordered_leader_list = new List <INST>();

            for (int j = 0; j < instruction_count; ++j)
            {
                // Order jump targets. These denote locations
                // where to split blocks. However, it's ordered,
                // so that splitting is done from last instruction in block
                // to first instruction in block.
                INST i = basic_block.Instructions[j];
                if (split_point.Contains(i,
                                         new LambdaComparer <INST>(
                                             (INST a, INST b)
                                             =>
                {
                    if (a.Offset != b.Offset)
                    {
                        return(false);
                    }
                    if (a.OpCode != b.OpCode)
                    {
                        return(false);
                    }
                    return(true);
                })))
                {
                    ordered_leader_list.Add(i);
                }
            }

            if (ordered_leader_list.Count != split_point.Count)
            {
                throw new Exception(
                          "Mono Cecil giving weird results for instruction operand type casting. Size of original split points not the same as order list of split points.");
            }

            // Split block at all jump targets.
            foreach (INST i in ordered_leader_list)
            {
                var owner = Cfg.PeekChangeSet(change_set).Where(
                    n => n.Instructions.Where(ins =>
                {
                    if (ins.Offset != i.Offset)
                    {
                        return(false);
                    }
                    if (ins.OpCode != i.OpCode)
                    {
                        return(false);
                    }
                    return(true);
                }
                                              ).Any()).ToList();
                // Check if there are multiple nodes with the same instruction or if there isn't
                // any node found containing the instruction. Either way, it's a programming error.
                if (owner.Count != 1)
                {
                    throw new Exception("Cannot find instruction!");
                }
                CFG.Vertex target_node = owner.FirstOrDefault();
                var        j           = target_node.Instructions.FindIndex(a =>
                {
                    if (a.Offset != i.Offset)
                    {
                        return(false);
                    }
                    if (a.OpCode != i.OpCode)
                    {
                        return(false);
                    }
                    return(true);
                });
                CFG.Vertex new_node = Split(target_node, j);
            }


            LambdaComparer <Instruction> fixed_comparer = new LambdaComparer <Instruction>(
                (Instruction a, Instruction b)
                => a.Offset == b.Offset &&
                a.OpCode == b.OpCode
                );

            // Add in all edges.
            var list_new_nodes = Cfg.PopChangeSet(change_set);

            foreach (var node in list_new_nodes)
            {
                int  node_instruction_count = node.Instructions.Count;
                INST last_instruction       = node.Instructions[node_instruction_count - 1];

                Mono.Cecil.Cil.OpCode      opcode       = last_instruction.OpCode;
                Mono.Cecil.Cil.FlowControl flow_control = opcode.FlowControl;

                // Add jump edge.
                switch (flow_control)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                {
                    // Two cases: i.Operand is a single instruction, or an array of instructions.
                    if (last_instruction.Operand as Mono.Cecil.Cil.Instruction != null)
                    {
                        // Handel leave instructions with code below.
                        if (!(last_instruction.OpCode.Code == Code.Leave ||
                              last_instruction.OpCode.Code == Code.Leave_S))
                        {
                            Mono.Cecil.Cil.Instruction target_instruction =
                                last_instruction.Operand as Mono.Cecil.Cil.Instruction;
                            CFG.Vertex target_node = list_new_nodes.FirstOrDefault(
                                (CFG.Vertex x) =>
                                {
                                    if (!fixed_comparer.Equals(x.Instructions.First().Instruction,
                                                               target_instruction))
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                            if (target_node != null)
                            {
                                Cfg.AddEdge(new CFG.Edge()
                                    {
                                        From = node, To = target_node
                                    });
                            }
                        }
                    }
                    else if (last_instruction.Operand as Mono.Cecil.Cil.Instruction[] != null)
                    {
                        foreach (Mono.Cecil.Cil.Instruction target_instruction in
                                 (last_instruction.Operand as Mono.Cecil.Cil.Instruction[]))
                        {
                            CFG.Vertex target_node = list_new_nodes.FirstOrDefault(
                                (CFG.Vertex x) =>
                                {
                                    if (!fixed_comparer.Equals(x.Instructions.First().Instruction, target_instruction))
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                            if (target_node != null)
                            {
                                Cfg.AddEdge(new CFG.Edge()
                                    {
                                        From = node, To = target_node
                                    });
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for conditional branch.");
                    }
                    break;
                }
                }

                // Add fall through edge.
                switch (flow_control)
                {
                //case Mono.Cecil.Cil.FlowControl.Branch:
                //case Mono.Cecil.Cil.FlowControl.Break:
                case Mono.Cecil.Cil.FlowControl.Call:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                case Mono.Cecil.Cil.FlowControl.Meta:
                case Mono.Cecil.Cil.FlowControl.Next:
                case Mono.Cecil.Cil.FlowControl.Phi:
                case Mono.Cecil.Cil.FlowControl.Throw:
                {
                    int next = instructions_before_splits.FindIndex(
                        n =>
                        {
                            var r = n == last_instruction;
                            return(r);
                        }
                        );
                    if (next < 0)
                    {
                        break;
                    }
                    next += 1;
                    if (next >= instructions_before_splits.Count)
                    {
                        break;
                    }
                    var        next_instruction = instructions_before_splits[next];
                    var        owner            = next_instruction.Block;
                    CFG.Vertex target_node      = owner;
                    Cfg.AddEdge(new CFG.Edge()
                        {
                            From = node, To = target_node
                        });
                }
                break;

                case Mono.Cecil.Cil.FlowControl.Return:
                    if (last_instruction.Instruction.OpCode.Code == Code.Endfinally)
                    {
                        // Although the exception handling is like a procedure call,
                        // local variables are all accessible. So, we need to copy stack
                        // values around. In addition, we have to create a fall through
                        // even though there is stack unwinding.
                        int next = instructions_before_splits.FindIndex(
                            n =>
                        {
                            var r = n == last_instruction;
                            return(r);
                        }
                            );
                        if (next < 0)
                        {
                            break;
                        }
                        next += 1;
                        if (next >= instructions_before_splits.Count)
                        {
                            break;
                        }
                        var        next_instruction = instructions_before_splits[next];
                        var        owner            = next_instruction.Block;
                        CFG.Vertex target_node      = owner;
                        Cfg.AddEdge(new CFG.Edge()
                        {
                            From = node, To = target_node
                        });
                    }
                    break;
                }
            }

            // Get inclusive start/exclusive end ranges of try/catch/finally.
            Dictionary <int, int> exclusive_eh_range = new Dictionary <int, int>();

            foreach (var eh in body.ExceptionHandlers)
            {
                int try_start = eh.TryStart.Offset;
                int eh_end    = eh.TryEnd != null ? eh.TryEnd.Offset : 0;
                if (eh.TryEnd != null && eh.TryEnd.Offset > eh_end)
                {
                    eh_end = eh.TryEnd.Offset;
                }
                if (eh.HandlerEnd != null && eh.HandlerEnd.Offset > eh_end)
                {
                    eh_end = eh.HandlerEnd.Offset;
                }
                exclusive_eh_range[try_start] = eh_end;
            }
            // Get inclusive start/inclusive end ranges of try/catch/finally.
            Dictionary <int, int> inclusive_eh_range = new Dictionary <int, int>();

            foreach (var pair in exclusive_eh_range)
            {
                int previous_instruction_address = 0;
                foreach (var i in body.Instructions)
                {
                    if (pair.Value == i.Offset)
                    {
                        inclusive_eh_range[pair.Key] = previous_instruction_address;
                        break;
                    }
                    previous_instruction_address = i.Offset;
                }
            }
            // Get "finally" blocks for each try, if there is one.
            Dictionary <int, CFG.Vertex> try_finally_block = new Dictionary <int, CFG.Vertex>();

            foreach (var eh in body.ExceptionHandlers)
            {
                if (eh.HandlerType == ExceptionHandlerType.Finally)
                {
                    var finally_entry_block = list_new_nodes.Where(
                        n =>
                    {
                        var first = n.Instructions.First().Instruction;
                        if (first.Offset == eh.HandlerStart.Offset)
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }).First();
                    try_finally_block[eh.TryStart.Offset] = finally_entry_block;
                }
            }
            // Set block properties.
            foreach (var eh in body.ExceptionHandlers)
            {
                var block = list_new_nodes.Where(
                    n =>
                {
                    var first = n.Instructions.First().Instruction;
                    if (first.Offset == eh.HandlerStart.Offset)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }).First();
                block.CatchType        = eh.CatchType;
                block.IsCatch          = eh.HandlerType == ExceptionHandlerType.Catch;
                block.ExceptionHandler = eh;
            }
            // Get "try" block for each try.
            Dictionary <int, CFG.Vertex> try_entry_block = new Dictionary <int, CFG.Vertex>();

            foreach (var pair in inclusive_eh_range)
            {
                int start       = pair.Key;
                var entry_block = list_new_nodes.Where(
                    n =>
                {
                    var first = n.Instructions.First().Instruction;
                    if (first.Offset == start)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }).First();
                try_entry_block[start] = entry_block;
            }
            // Get entry block for each exception handler.
            Dictionary <int, CFG.Vertex> eh_entry_block = new Dictionary <int, CFG.Vertex>();

            foreach (var eh in body.ExceptionHandlers)
            {
                int start       = eh.HandlerStart.Offset;
                var entry_block = list_new_nodes.Where(
                    n =>
                {
                    var first = n.Instructions.First().Instruction;
                    if (first.Offset == start)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }).First();
                eh_entry_block[start] = entry_block;
            }

            foreach (var eh in body.ExceptionHandlers)
            {
                int start     = eh.TryStart.Offset;
                var try_block = try_entry_block[start];
                int eh_start  = eh.HandlerStart.Offset;
                var eh_block  = eh_entry_block[eh_start];
                if (eh.HandlerType == ExceptionHandlerType.Finally)
                {
                    continue;
                }
                foreach (var prev in list_new_nodes.First()._graph.Predecessors(try_block))
                {
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = prev, To = eh_block
                    });
                }
            }

            // Go through all CIL "leave" instructions and draw up edges. Any leave to end of
            // endfinally block requires edge to finally block, not the following instruction.
            foreach (var node in list_new_nodes)
            {
                int  node_instruction_count             = node.Instructions.Count;
                INST leave_instruction                  = node.Instructions[node_instruction_count - 1];
                Mono.Cecil.Cil.OpCode      opcode       = leave_instruction.OpCode;
                Mono.Cecil.Cil.FlowControl flow_control = opcode.FlowControl;
                if (!(leave_instruction.OpCode.Code == Code.Leave || leave_instruction.OpCode.Code == Code.Leave_S))
                {
                    continue;
                }

                // Link up any leave instructions
                object operand = leave_instruction.Operand;
                Mono.Cecil.Cil.Instruction   single_instruction    = operand as Mono.Cecil.Cil.Instruction;
                Mono.Cecil.Cil.Instruction[] array_of_instructions = operand as Mono.Cecil.Cil.Instruction[];
                if (single_instruction == null)
                {
                    throw new Exception("Malformed leave instruction.");
                }
                KeyValuePair <int, int> pair = inclusive_eh_range.Where(p => p.Key <= leave_instruction.Instruction.Offset &&
                                                                        leave_instruction.Instruction.Offset <= p.Value).FirstOrDefault();
                // pair indicates what try/catch/finally block. If not in a try/catch/finally,
                // draw edge to destination. If the destination is outside try/catch/finally,
                // draw edge to destination.
                if (pair.Value == 0 || single_instruction.Offset >= pair.Key && single_instruction.Offset <= pair.Value)
                {
                    var whereever = list_new_nodes.Where(
                        n =>
                    {
                        var first = n.Instructions.First().Instruction;
                        if (first.Offset == single_instruction.Offset)
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }).First();
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = node, To = whereever
                    });
                    continue;
                }
                if (try_finally_block.ContainsKey(pair.Key))
                {
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = node, To = try_finally_block[pair.Key]
                    });
                }
                else
                {
                    var whereever = list_new_nodes.Where(
                        n =>
                    {
                        var first = n.Instructions.First().Instruction;
                        if (first.Offset == single_instruction.Offset)
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }).First();
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = node, To = whereever
                    });
                }
            }

            if (Campy.Utils.Options.IsOn("detailed_import_computation_trace"))
            {
                Cfg.OutputDotGraph();
            }
            if (Campy.Utils.Options.IsOn("detailed_import_computation_trace"))
            {
                Cfg.OutputEntireGraph();
            }
        }
Пример #32
0
        public void Classes_with_multiple_equal_compared_valeus_are_equal()
        {
            var comparer = new LambdaComparer<ClassWithProperties>(x => x.IntegerValue, x => x.StringValue);

            Assert.IsTrue(comparer.Equals(_left, _right));
        }
Пример #33
0
        internal static IncrementalValuesProvider <T> WithLambdaComparer <T>(this IncrementalValuesProvider <T> source, Func <T, T, bool> equal, Func <T, int> getHashCode)
        {
            var comparer = new LambdaComparer <T>(equal, getHashCode);

            return(source.WithComparer(comparer));
        }
        public void AreEqual(Expression left, Expression right)
        {
            var exc = new LambdaComparer();

            Assert.True(exc.Equals(left, right));
        }