Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ResolveGenericsVisitor.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using Mono.Cecil;
7 
8 namespace SiliconStudio.AssemblyProcessor
9 {
10  /// <summary>
11  /// Transform open generic types to closed instantiation using context information.
12  /// See <see cref="Process"/> for more details.
13  /// </summary>
15  {
16  private Dictionary<TypeReference, TypeReference> genericTypeMapping;
17 
18  public ResolveGenericsVisitor(Dictionary<TypeReference, TypeReference> genericTypeMapping)
19  {
20  this.genericTypeMapping = genericTypeMapping;
21  }
22 
23  /// <summary>
24  /// Transform open generic types to closed instantiation using context information.
25  /// As an example, if B{T} inherits from A{T}, running it with B{C} as context and A{B.T} as type, ti will return A{C}.
26  /// </summary>
27  public static TypeReference Process(TypeReference context, TypeReference type)
28  {
29  if (type == null)
30  return null;
31 
32  var genericInstanceTypeContext = context as GenericInstanceType;
33  if (genericInstanceTypeContext == null)
34  return type;
35 
36  if (genericInstanceTypeContext.ContainsGenericParameter())
37  return type;
38 
39  // Build dictionary that will map generic type to their real implementation type
40  var resolvedType = context.Resolve();
41  var genericTypeMapping = new Dictionary<TypeReference, TypeReference>();
42  for (int i = 0; i < resolvedType.GenericParameters.Count; ++i)
43  {
44  var genericParameter = context.GetElementType().Resolve().GenericParameters[i];
45  genericTypeMapping.Add(genericParameter, genericInstanceTypeContext.GenericArguments[i]);
46  }
47 
48  var visitor = new ResolveGenericsVisitor(genericTypeMapping);
49  var result = visitor.VisitDynamic(type);
50 
51  // Make sure type is closed now
52  if (result.ContainsGenericParameter())
53  throw new InvalidOperationException("Unsupported generic resolution.");
54 
55  return result;
56  }
57 
58  public override TypeReference Visit(GenericParameter type)
59  {
60  TypeReference result;
61  if (genericTypeMapping.TryGetValue(type, out result))
62  return result;
63 
64  return base.Visit(type);
65  }
66  }
67 }
override TypeReference Visit(GenericParameter type)
static TypeReference Process(TypeReference context, TypeReference type)
Transform open generic types to closed instantiation using context information. As an example...
ResolveGenericsVisitor(Dictionary< TypeReference, TypeReference > genericTypeMapping)
Transform open generic types to closed instantiation using context information. See Process for more ...
Visit Cecil types recursively, and replace them if requested.