File: System.Activities.Presentation\System\Activities\Presentation\ActivityDelegateUtilities.cs
Project: ndp\cdf\src\NetFx40\Tools\System.Activities.Presentation.csproj (System.Activities.Presentation)
//----------------------------------------------------------------
// <copyright company="Microsoft Corporation">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//----------------------------------------------------------------
 
namespace System.Activities.Presentation
{
    using System.Activities.Presentation.Metadata;
    using System.Activities.Presentation.Model;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Runtime;
 
    internal static class ActivityDelegateUtilities
    {
        public static ActivityDelegateMetadata GetMetadata(Type type)
        {
            ActivityDelegateMetadata metadata = new ActivityDelegateMetadata();
 
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
 
            foreach (PropertyInfo property in properties)
            {
                if (property.PropertyType.IsGenericType)
                {
                    ActivityDelegateArgumentMetadata argument = null;
                    if (property.PropertyType.GetGenericTypeDefinition() == typeof(DelegateInArgument<>))
                    {
                        argument = new ActivityDelegateArgumentMetadata();
                        argument.Direction = ActivityDelegateArgumentDirection.In;
                    }
                    else if (property.PropertyType.GetGenericTypeDefinition() == typeof(DelegateOutArgument<>))
                    {
                        argument = new ActivityDelegateArgumentMetadata();
                        argument.Direction = ActivityDelegateArgumentDirection.Out;
                    }
 
                    if (argument != null)
                    {
                        argument.Name = property.Name;
                        argument.Type = property.PropertyType.GetGenericArguments()[0];
                        metadata.Add(argument);
                    }
                }
            }
 
            return metadata;
        }
 
        public static void FillDelegate(ActivityDelegate activityDelegate, ActivityDelegateMetadata metadata)
        {
            foreach (ActivityDelegateArgumentMetadata argument in metadata)
            {
                activityDelegate.GetType().GetProperty(argument.Name).SetValue(activityDelegate, CreateDelegateArgument(argument), null);
            }
        }
 
        public static bool HasActivityDelegate(Type type)
        {
            return GetPropertiesByHeuristics(type).Count > 0;
        }
 
        public static List<ActivityDelegateInfo> CreateActivityDelegateInfo(ModelItem activity)
        {
            List<ActivityDelegateInfo> list = new List<ActivityDelegateInfo>();
 
            foreach (PropertyInfo property in GetPropertiesByHeuristics(activity.ItemType))
            {
                list.Add(new ActivityDelegateInfo(activity, property.Name));
            }
 
            return list;
        }
 
        // Heuristics:
        // A property is considered to be an ActivityDelegate when
        //   1. it is a public instance property
        //   2. it has a public getter and a public setter
        //   3. its type is derived from ActivityDelegate
        //   4. can create an isntance of its type
        private static List<PropertyInfo> GetPropertiesByHeuristics(Type activityType)
        {
            List<PropertyInfo> result = new List<PropertyInfo>();
 
            PropertyInfo[] properties = activityType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo property in properties)
            {
                if (property.GetGetMethod() != null &&
                    property.GetSetMethod() != null &&
                    property.PropertyType.IsSubclassOf(typeof(ActivityDelegate)) &&
                    TypeUtilities.CanCreateInstanceUsingDefaultConstructor(property.PropertyType))
                {
                    result.Add(property);
                }
            }
 
            result.Sort(new PropertyInfoComparer());
 
            return result;
        }
 
        private static DelegateArgument CreateDelegateArgument(ActivityDelegateArgumentMetadata argument)
        {
            DelegateArgument delegateArgument = null;
            if (argument.Direction == ActivityDelegateArgumentDirection.In)
            {
                delegateArgument = Activator.CreateInstance(typeof(DelegateInArgument<>).MakeGenericType(argument.Type)) as DelegateArgument;
            }
            else
            {
                delegateArgument = Activator.CreateInstance(typeof(DelegateOutArgument<>).MakeGenericType(argument.Type)) as DelegateArgument;
            }
 
            delegateArgument.Name = argument.Name;
 
            return delegateArgument;
        }
 
        private class PropertyInfoComparer : IComparer<PropertyInfo>
        {
            public int Compare(PropertyInfo x, PropertyInfo y)
            {
                Fx.Assert(x != null, "x should not be null");
                Fx.Assert(y != null, "y should not be null");
 
                return StringComparer.Ordinal.Compare(x.Name, y.Name);
            }
        }
    }
}