[reflection] Coop handles icalls in System.Reflection and System.RuntimeTypeHandle...
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / ActivityDelegateUtilities.cs
1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //----------------------------------------------------------------
6
7 namespace System.Activities.Presentation
8 {
9     using System.Activities.Presentation.Metadata;
10     using System.Activities.Presentation.Model;
11     using System.Collections.Generic;
12     using System.Reflection;
13     using System.Runtime;
14
15     internal static class ActivityDelegateUtilities
16     {
17         public static ActivityDelegateMetadata GetMetadata(Type type)
18         {
19             ActivityDelegateMetadata metadata = new ActivityDelegateMetadata();
20
21             PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
22
23             foreach (PropertyInfo property in properties)
24             {
25                 if (property.PropertyType.IsGenericType)
26                 {
27                     ActivityDelegateArgumentMetadata argument = null;
28                     if (property.PropertyType.GetGenericTypeDefinition() == typeof(DelegateInArgument<>))
29                     {
30                         argument = new ActivityDelegateArgumentMetadata();
31                         argument.Direction = ActivityDelegateArgumentDirection.In;
32                     }
33                     else if (property.PropertyType.GetGenericTypeDefinition() == typeof(DelegateOutArgument<>))
34                     {
35                         argument = new ActivityDelegateArgumentMetadata();
36                         argument.Direction = ActivityDelegateArgumentDirection.Out;
37                     }
38
39                     if (argument != null)
40                     {
41                         argument.Name = property.Name;
42                         argument.Type = property.PropertyType.GetGenericArguments()[0];
43                         metadata.Add(argument);
44                     }
45                 }
46             }
47
48             return metadata;
49         }
50
51         public static void FillDelegate(ActivityDelegate activityDelegate, ActivityDelegateMetadata metadata)
52         {
53             foreach (ActivityDelegateArgumentMetadata argument in metadata)
54             {
55                 activityDelegate.GetType().GetProperty(argument.Name).SetValue(activityDelegate, CreateDelegateArgument(argument), null);
56             }
57         }
58
59         public static bool HasActivityDelegate(Type type)
60         {
61             return GetPropertiesByHeuristics(type).Count > 0;
62         }
63
64         public static List<ActivityDelegateInfo> CreateActivityDelegateInfo(ModelItem activity)
65         {
66             List<ActivityDelegateInfo> list = new List<ActivityDelegateInfo>();
67
68             foreach (PropertyInfo property in GetPropertiesByHeuristics(activity.ItemType))
69             {
70                 list.Add(new ActivityDelegateInfo(activity, property.Name));
71             }
72
73             return list;
74         }
75
76         // Heuristics:
77         // A property is considered to be an ActivityDelegate when
78         //   1. it is a public instance property
79         //   2. it has a public getter and a public setter
80         //   3. its type is derived from ActivityDelegate
81         //   4. can create an isntance of its type
82         private static List<PropertyInfo> GetPropertiesByHeuristics(Type activityType)
83         {
84             List<PropertyInfo> result = new List<PropertyInfo>();
85
86             PropertyInfo[] properties = activityType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
87             foreach (PropertyInfo property in properties)
88             {
89                 if (property.GetGetMethod() != null &&
90                     property.GetSetMethod() != null &&
91                     property.PropertyType.IsSubclassOf(typeof(ActivityDelegate)) &&
92                     TypeUtilities.CanCreateInstanceUsingDefaultConstructor(property.PropertyType))
93                 {
94                     result.Add(property);
95                 }
96             }
97
98             result.Sort(new PropertyInfoComparer());
99
100             return result;
101         }
102
103         private static DelegateArgument CreateDelegateArgument(ActivityDelegateArgumentMetadata argument)
104         {
105             DelegateArgument delegateArgument = null;
106             if (argument.Direction == ActivityDelegateArgumentDirection.In)
107             {
108                 delegateArgument = Activator.CreateInstance(typeof(DelegateInArgument<>).MakeGenericType(argument.Type)) as DelegateArgument;
109             }
110             else
111             {
112                 delegateArgument = Activator.CreateInstance(typeof(DelegateOutArgument<>).MakeGenericType(argument.Type)) as DelegateArgument;
113             }
114
115             delegateArgument.Name = argument.Name;
116
117             return delegateArgument;
118         }
119
120         private class PropertyInfoComparer : IComparer<PropertyInfo>
121         {
122             public int Compare(PropertyInfo x, PropertyInfo y)
123             {
124                 Fx.Assert(x != null, "x should not be null");
125                 Fx.Assert(y != null, "y should not be null");
126
127                 return StringComparer.Ordinal.Compare(x.Name, y.Name);
128             }
129         }
130     }
131 }