using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Delegates
{
    class Examples15_20
    {
        // Listing 9-15
        public static bool IsLongString(object o)
        {
            var s = o as string;
            return s != null && s.Length > 20;
        }


        static void Main(string[] args)
        {
            Predicate<object> po = IsLongString;
            Predicate<string> ps = po;
            Console.WriteLine(ps("Zbyt krótki."));
        }

        // Kod umieszczony w komentarzu gdyż ilustruje błąd.
        //public static void IllegalConversion()
        //{
        //    // Listing 9-16
        //    Predicate<string> pred = IsLongString;
        //    Func<string, bool> f = pred;  // Spowoduje zgłoszenie błędu kompilacji
        //}

        public static void DelegateRefToOtherDelegate()
        {
            // Listing 9-17
            Predicate<string> pred = IsLongString;
            var pred2 = new Func<string, bool>(pred);
        }

        public static void DelegateExplicitRefToOtherDelegate()
        {
            // Listing 9-18
            Predicate<string> pred = IsLongString;
            var pred2 = new Func<string, bool>(pred.Invoke);
        }

        public static void CreateNewDelegateWithSameTargetAsExisting()
        {
            // Listing 9-19
            Predicate<string> pred = IsLongString;
            var pred2 = (Func<string, bool>) Delegate.CreateDelegate(
                typeof(Func<string, bool>), pred.Target, pred.Method);

        }

        // Listing 9-20
        public static TResult DuplicateDelegateAs<TResult>(MulticastDelegate source)
        {
            Delegate result = null;
            foreach (Delegate sourceItem in source.GetInvocationList())
            {
                var copy = Delegate.CreateDelegate(
                    typeof(TResult), sourceItem.Target, sourceItem.Method);
                result = Delegate.Combine(result, copy);
            }

            return (TResult) (object) result;
        }
    }
}
