Update Project

This commit is contained in:
2026-03-20 13:04:43 +02:00
parent 9b587e6cba
commit beae2dea89
2295 changed files with 251259 additions and 33 deletions
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 1f7a08e3d1279e542954d80ff88dcd95
folderAsset: yes
timeCreated: 1537245053
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,382 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ModestTree;
using Zenject.ReflectionBaking.Mono.Cecil;
using Zenject.ReflectionBaking.Mono.Collections.Generic;
using ICustomAttributeProvider = Zenject.ReflectionBaking.Mono.Cecil.ICustomAttributeProvider;
namespace Zenject.ReflectionBaking
{
public static class CecilExtensions
{
public static Type TryGetActualType(this TypeReference typeRef, Assembly assembly)
{
var reflectionName = GetReflectionName(typeRef);
return assembly.GetType(reflectionName);
}
static string GetReflectionName(TypeReference type)
{
if (type.IsGenericInstance)
{
var genericInstance = (GenericInstanceType)type;
return string.Format(
"{0}.{1}[{2}]", genericInstance.Namespace, type.Name,
String.Join(",", genericInstance.GenericArguments.Select(p => GetReflectionName(p)).ToArray()));
}
return type.FullName;
}
public static List<TypeDefinition> LookupAllTypes(this ModuleDefinition module)
{
var allTypes = new List<TypeDefinition>();
foreach (var type in module.Types)
{
LookupAllTypesInternal(type, allTypes);
}
return allTypes;
}
static void LookupAllTypesInternal(TypeDefinition type, List<TypeDefinition> buffer)
{
buffer.Add(type);
foreach (var nestedType in type.NestedTypes)
{
LookupAllTypesInternal(nestedType, buffer);
}
}
public static TypeReference ImportType<T>(this ModuleDefinition module)
{
return module.ImportType(typeof(T));
}
public static TypeReference ImportType(this ModuleDefinition module, Type type)
{
return module.Import(type);
}
public static MethodReference ImportMethod<T>(this ModuleDefinition module, string methodName)
{
return module.ImportMethod(typeof(T), methodName);
}
public static MethodReference ImportMethod(
this ModuleDefinition module, Type type, string methodName)
{
return module.Import(
module.ImportType(type).Resolve().GetMethod(methodName));
}
public static MethodReference ImportMethod<T>(
this ModuleDefinition module, string methodName, int numArgs)
{
return module.ImportMethod(typeof(T), methodName, numArgs);
}
public static MethodReference ImportMethod(
this ModuleDefinition module, Type type, string methodName, int numArgs)
{
return module.Import(
module.ImportType(type).Resolve().GetMethod(methodName, numArgs));
}
public static MethodDefinition GetMethod(this TypeDefinition instance, string name)
{
for (int i = 0; i < instance.Methods.Count; i++)
{
MethodDefinition methodDef = instance.Methods[i];
if (string.CompareOrdinal(methodDef.Name, name) == 0)
{
return methodDef;
}
}
return null;
}
public static MethodDefinition GetMethod(this TypeDefinition instance, string name, params Type[] parameterTypes)
{
for (int i = 0; i < instance.Methods.Count; i++)
{
MethodDefinition methodDefinition = instance.Methods[i];
if (!string.Equals(methodDefinition.Name, name, StringComparison.Ordinal) ||
parameterTypes.Length != methodDefinition.Parameters.Count)
{
continue;
}
MethodDefinition result = methodDefinition;
for (int x = methodDefinition.Parameters.Count - 1; x >= 0; x--)
{
ParameterDefinition parameter = methodDefinition.Parameters[x];
if (!string.Equals(parameter.ParameterType.Name, parameterTypes[x].Name, StringComparison.Ordinal))
{
break;
}
if (x == 0)
{
return result;
}
}
}
return null;
}
public static MethodDefinition GetMethod(this TypeDefinition instance, string name, params TypeReference[] parameterTypes)
{
if (instance.Methods != null)
{
for (int i = 0; i < instance.Methods.Count; i++)
{
MethodDefinition methodDefinition = instance.Methods[i];
if (string.Equals(methodDefinition.Name, name, StringComparison.Ordinal) // Names Match
&& parameterTypes.Length == methodDefinition.Parameters.Count) // The same number of parameters
{
MethodDefinition result = methodDefinition;
for (int x = methodDefinition.Parameters.Count - 1; x >= 0; x--)
{
ParameterDefinition parameter = methodDefinition.Parameters[x];
if (!string.Equals(parameter.ParameterType.Name, parameterTypes[x].Name, StringComparison.Ordinal))
{
break;
}
if (x == 0)
{
return result;
}
}
}
}
}
return null;
}
public static MethodDefinition GetMethod(this TypeDefinition instance, string name, int argCount)
{
for (int i = 0; i < instance.Methods.Count; i++)
{
MethodDefinition methodDef = instance.Methods[i];
if (string.CompareOrdinal(methodDef.Name, name) == 0 && methodDef.Parameters.Count == argCount)
{
return methodDef;
}
}
return null;
}
public static PropertyDefinition GetPropertyDefinition(this TypeDefinition instance, string name)
{
for (int i = 0; i < instance.Properties.Count; i++)
{
PropertyDefinition preopertyDef = instance.Properties[i];
// Properties can only have one argument or they are an indexer.
if (string.CompareOrdinal(preopertyDef.Name, name) == 0 && preopertyDef.Parameters.Count == 0)
{
return preopertyDef;
}
}
return null;
}
public static bool HasCustomAttribute<T>(this ICustomAttributeProvider instance)
{
if (!instance.HasCustomAttributes)
{
return false;
}
Collection<CustomAttribute> attributes = instance.CustomAttributes;
for(int i = 0; i < attributes.Count; i++)
{
if (attributes[i].AttributeType.FullName.Equals(typeof(T).FullName, StringComparison.Ordinal))
{
return true;
}
}
return false;
}
public static MethodReference ChangeDeclaringType(
this MethodReference methodDef, TypeReference typeRef)
{
var newMethodRef = new MethodReference(
methodDef.Name, methodDef.ReturnType, typeRef);
newMethodRef.HasThis = methodDef.HasThis;
foreach (var arg in methodDef.Parameters)
{
var paramDef = new ParameterDefinition(arg.ParameterType);
newMethodRef.Parameters.Add(paramDef);
}
return newMethodRef;
}
public static FieldReference ChangeDeclaringType(
this FieldReference fieldDef, TypeReference typeRef)
{
return new FieldReference(
fieldDef.Name, fieldDef.FieldType, typeRef);
}
public static CustomAttribute GetCustomAttribute<T>(this ICustomAttributeProvider instance)
{
if (!instance.HasCustomAttributes)
{
return null;
}
Collection<CustomAttribute> attributes = instance.CustomAttributes;
for (int i = 0; i < attributes.Count; i++)
{
if (attributes[i].AttributeType.FullName.Equals(typeof(T).FullName, StringComparison.Ordinal))
{
return attributes[i];
}
}
return null;
}
public static IEnumerable<TypeReference> GetSpecificBaseTypesAndSelf(
this TypeReference specificTypeRef)
{
yield return specificTypeRef;
foreach (var ancestor in specificTypeRef.GetSpecificBaseTypesAndSelf())
{
yield return ancestor;
}
}
public static IEnumerable<TypeReference> GetSpecificBaseTypes(
this TypeReference specificTypeRef)
{
var specificBaseTypeRef = specificTypeRef.TryGetSpecificBaseType();
if (specificBaseTypeRef != null)
{
yield return specificBaseTypeRef;
foreach (var ancestor in GetSpecificBaseTypes(specificBaseTypeRef))
{
yield return ancestor;
}
}
}
public static IEnumerable<TypeReference> AllNestParentsAndSelf(this TypeReference specificTypeRef)
{
yield return specificTypeRef;
foreach (var ancestor in specificTypeRef.AllNestParents())
{
yield return ancestor;
}
}
public static IEnumerable<TypeReference> AllNestParents(this TypeReference specificTypeRef)
{
if (specificTypeRef.DeclaringType != null)
{
yield return specificTypeRef.DeclaringType;
foreach (var ancestor in specificTypeRef.DeclaringType.AllNestParents())
{
yield return ancestor;
}
}
}
public static TypeReference TryResolve(this TypeReference typeRef)
{
try
{
return typeRef.Resolve();
}
catch
{
return null;
}
}
public static TypeReference TryGetSpecificBaseType(this TypeReference specificTypeRef)
{
var typeDef = specificTypeRef.Resolve();
if (typeDef.BaseType == null
|| typeDef.BaseType.FullName == "System.Object")
{
return null;
}
var specificBaseTypeRef = typeDef.BaseType;
if (specificBaseTypeRef.ContainsGenericParameter)
{
var genericArgMap = new Dictionary<string, TypeReference>();
foreach (var ancestor in specificTypeRef.AllNestParentsAndSelf())
{
var specificTypeRefGenericInstance = ancestor as GenericInstanceType;
if (specificTypeRefGenericInstance != null)
{
for (int i = 0; i < typeDef.GenericParameters.Count; i++)
{
genericArgMap[typeDef.GenericParameters[i].Name] = specificTypeRefGenericInstance.GenericArguments[i];
}
}
}
specificBaseTypeRef = FillInGenericParameters(specificBaseTypeRef, genericArgMap);
}
return specificBaseTypeRef;
}
public static TypeReference FillInGenericParameters(
TypeReference type, Dictionary<string, TypeReference> genericArgMap)
{
var genericType = type as GenericInstanceType;
Assert.IsNotNull(genericType);
var genericTypeClone = new GenericInstanceType(type.Resolve());
for (int i = 0; i < genericType.GenericArguments.Count; i++)
{
var arg = genericType.GenericArguments[i];
if (arg.IsGenericParameter)
{
Assert.That(genericArgMap.ContainsKey(arg.Name), "Could not find key '{0}' for type '{1}'", arg.Name, type.FullName);
genericTypeClone.GenericArguments.Add(genericArgMap[arg.Name]);
}
else
{
genericTypeClone.GenericArguments.Add(arg);
}
}
return genericTypeClone;
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 89602ba5a473d064387392d8d2055aa4
timeCreated: 1537234617
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,752 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using ModestTree;
using Zenject.Internal;
using Zenject.ReflectionBaking.Mono.Cecil;
using Zenject.ReflectionBaking.Mono.Cecil.Cil;
using Zenject.ReflectionBaking.Mono.Collections.Generic;
using MethodAttributes = Zenject.ReflectionBaking.Mono.Cecil.MethodAttributes;
namespace Zenject.ReflectionBaking
{
public class ReflectionBakingModuleEditor
{
readonly Assembly _assembly;
readonly ModuleDefinition _module;
readonly List<Regex> _namespaceRegexes;
MethodReference _zenjectTypeInfoConstructor;
MethodReference _injectableInfoConstructor;
MethodReference _injectMethodInfoConstructor;
MethodReference _injectMemberInfoConstructor;
MethodReference _constructorInfoConstructor;
MethodReference _getTypeFromHandleMethod;
MethodReference _funcConstructor;
MethodReference _funcPostInject;
MethodReference _funcMemberSetter;
MethodReference _preserveConstructor;
TypeReference _injectMethodInfoType;
TypeReference _injectMemberInfoType;
TypeReference _injectableInfoType;
TypeReference _objectArrayType;
TypeReference _zenjectTypeInfoType;
ReflectionBakingModuleEditor(
ModuleDefinition module, Assembly assembly, List<string> namespacePatterns)
{
_module = module;
_assembly = assembly;
_namespaceRegexes = namespacePatterns.Select(CreateRegex).ToList();
_namespaceRegexes.Add(CreateRegex("^Zenject"));
}
public static int WeaveAssembly(
ModuleDefinition module, Assembly assembly)
{
return WeaveAssembly(module, assembly, new List<string>());
}
public static int WeaveAssembly(
ModuleDefinition module, Assembly assembly, List<string> namespacePatterns)
{
return new ReflectionBakingModuleEditor(module, assembly, namespacePatterns).Run();
}
int Run()
{
SaveImports();
int numTypesEditted = 0;
var allTypes = _module.LookupAllTypes();
foreach (var typeDef in allTypes)
{
if (_namespaceRegexes.Any() && !_namespaceRegexes.Any(x => x.IsMatch(typeDef.FullName)))
{
continue;
}
var actualType = typeDef.TryGetActualType(_assembly);
if (actualType == null)
{
Log.Warn("Could not find actual type for type '{0}', skipping", typeDef.FullName);
continue;
}
if (TryEditType(typeDef, actualType))
{
numTypesEditted++;
}
}
return numTypesEditted;
}
Regex CreateRegex(string regexStr)
{
return new Regex(regexStr, RegexOptions.Compiled);
}
void SaveImports()
{
_zenjectTypeInfoType = _module.ImportType<InjectTypeInfo>();
_zenjectTypeInfoConstructor = _module.ImportMethod<InjectTypeInfo>(".ctor");
_injectableInfoConstructor = _module.ImportMethod<InjectableInfo>(".ctor");
_getTypeFromHandleMethod = _module.ImportMethod<Type>("GetTypeFromHandle", 1);
_injectMethodInfoType = _module.ImportType<InjectTypeInfo.InjectMethodInfo>();
_injectMethodInfoConstructor = _module.ImportMethod<InjectTypeInfo.InjectMethodInfo>(".ctor");
_injectMemberInfoType = _module.ImportType<InjectTypeInfo.InjectMemberInfo>();
_injectMemberInfoConstructor = _module.ImportMethod<InjectTypeInfo.InjectMemberInfo>(".ctor");
_preserveConstructor = _module.ImportMethod<Zenject.Internal.PreserveAttribute>(".ctor");
_constructorInfoConstructor = _module.ImportMethod<InjectTypeInfo.InjectConstructorInfo>(".ctor");
_injectableInfoType = _module.ImportType<InjectableInfo>();
_objectArrayType = _module.Import(typeof(object[]));
_funcConstructor = _module.ImportMethod<ZenFactoryMethod>(".ctor", 2);
_funcPostInject = _module.ImportMethod<ZenInjectMethod>(".ctor", 2);
_funcMemberSetter = _module.ImportMethod<ZenMemberSetterMethod>(".ctor", 2);
}
public bool TryEditType(TypeDefinition typeDef, Type actualType)
{
if (actualType.IsEnum || actualType.IsValueType || actualType.IsInterface
|| actualType.HasAttribute<NoReflectionBakingAttribute>()
|| IsStaticClass(actualType) || actualType.DerivesFromOrEqual<Delegate>() || actualType.DerivesFromOrEqual<Attribute>())
{
return false;
}
// Allow running on the same dll multiple times without causing problems
if (IsTypeProcessed(typeDef))
{
return false;
}
try
{
var typeInfo = ReflectionTypeAnalyzer.GetReflectionInfo(actualType);
var factoryMethod = TryAddFactoryMethod(typeDef, typeInfo);
var genericTypeDef = CreateGenericInstanceWithParameters(typeDef);
var fieldSetMethods = AddFieldSetters(typeDef, genericTypeDef, typeInfo);
var propertySetMethods = AddPropertySetters(typeDef, genericTypeDef, typeInfo);
var postInjectMethods = AddPostInjectMethods(typeDef, genericTypeDef, typeInfo);
CreateGetInfoMethod(
typeDef, genericTypeDef, typeInfo,
factoryMethod, fieldSetMethods, propertySetMethods, postInjectMethods);
}
catch (Exception e)
{
Log.ErrorException("Error when modifying type '{0}'".Fmt(actualType), e);
throw;
}
return true;
}
static bool IsStaticClass(Type type)
{
// Apparently this is unique to static classes
return type.IsAbstract && type.IsSealed;
}
// We are already processed if our static constructor calls TypeAnalyzer
bool IsTypeProcessed(TypeDefinition typeDef)
{
return typeDef.GetMethod(TypeAnalyzer.ReflectionBakingGetInjectInfoMethodName) != null;
}
void EmitCastOperation(ILProcessor processor, Type type, Collection<GenericParameter> genericParams)
{
if (type.IsGenericParameter)
{
processor.Emit(OpCodes.Unbox_Any, genericParams[type.GenericParameterPosition]);
}
else if (type.IsEnum)
{
processor.Emit(OpCodes.Unbox_Any, _module.TypeSystem.Int32);
}
else if (type.IsValueType)
{
processor.Emit(OpCodes.Unbox_Any, _module.ImportType(type));
}
else
{
processor.Emit(OpCodes.Castclass, CreateGenericInstanceIfNecessary(type, genericParams));
}
}
TypeReference CreateGenericInstanceWithParameters(TypeDefinition typeDef)
{
if (typeDef.GenericParameters.Any())
{
var genericInstance = new GenericInstanceType(typeDef);
foreach (var parameter in typeDef.GenericParameters)
{
genericInstance.GenericArguments.Add(parameter);
}
return genericInstance;
}
return typeDef;
}
MethodDefinition TryAddFactoryMethod(
TypeDefinition typeDef, ReflectionTypeInfo typeInfo)
{
if (typeInfo.Type.GetParentTypes().Any(x => x.FullName == "UnityEngine.Component"))
{
Assert.That(typeInfo.InjectConstructor.Parameters.IsEmpty());
return null;
}
if (typeInfo.InjectConstructor.ConstructorInfo == null)
{
// static classes, abstract types
return null;
}
var factoryMethod = new MethodDefinition(
TypeAnalyzer.ReflectionBakingFactoryMethodName,
MethodAttributes.Private | MethodAttributes.HideBySig |
MethodAttributes.Static,
_module.TypeSystem.Object);
var p1 = new ParameterDefinition(_objectArrayType);
p1.Name = "P_0";
factoryMethod.Parameters.Add(p1);
var body = factoryMethod.Body;
body.InitLocals = true;
var processor = body.GetILProcessor();
var returnValueVar = new VariableDefinition(_module.TypeSystem.Object);
body.Variables.Add(returnValueVar);
processor.Emit(OpCodes.Nop);
Assert.IsNotNull(typeInfo.InjectConstructor);
var args = typeInfo.InjectConstructor.Parameters;
for (int i = 0; i < args.Count; i++)
{
var arg = args[i];
processor.Emit(OpCodes.Ldarg_0);
processor.Emit(OpCodes.Ldc_I4, i);
processor.Emit(OpCodes.Ldelem_Ref);
EmitCastOperation(
processor, arg.ParameterInfo.ParameterType, typeDef.GenericParameters);
}
processor.Emit(OpCodes.Newobj, _module.Import(typeInfo.InjectConstructor.ConstructorInfo));
processor.Emit(OpCodes.Stloc_0);
processor.Emit(OpCodes.Ldloc_S, returnValueVar);
processor.Emit(OpCodes.Ret);
typeDef.Methods.Add(factoryMethod);
return factoryMethod;
}
void AddPostInjectMethodBody(
ILProcessor processor, ReflectionTypeInfo.InjectMethodInfo postInjectInfo, TypeDefinition typeDef, TypeReference genericTypeDef)
{
processor.Emit(OpCodes.Nop);
TypeReference declaringTypeDef;
MethodReference actualMethodDef;
if (!TryFindLocalMethod(
genericTypeDef, postInjectInfo.MethodInfo.Name, out declaringTypeDef, out actualMethodDef))
{
throw Assert.CreateException();
}
processor.Emit(OpCodes.Ldarg_0);
processor.Emit(OpCodes.Castclass, declaringTypeDef);
for (int k = 0; k < postInjectInfo.Parameters.Count; k++)
{
var injectInfo = postInjectInfo.Parameters[k];
processor.Emit(OpCodes.Ldarg_1);
processor.Emit(OpCodes.Ldc_I4, k);
processor.Emit(OpCodes.Ldelem_Ref);
EmitCastOperation(processor, injectInfo.ParameterInfo.ParameterType, typeDef.GenericParameters);
}
processor.Emit(OpCodes.Callvirt, actualMethodDef);
processor.Emit(OpCodes.Ret);
}
MethodDefinition AddPostInjectMethod(
string name, ReflectionTypeInfo.InjectMethodInfo postInjectInfo, TypeDefinition typeDef, TypeReference genericTypeDef)
{
var methodDef = new MethodDefinition(
name,
MethodAttributes.Private | MethodAttributes.HideBySig |
MethodAttributes.Static,
_module.TypeSystem.Void);
var p1 = new ParameterDefinition(_module.TypeSystem.Object);
p1.Name = "P_0";
methodDef.Parameters.Add(p1);
var p2 = new ParameterDefinition(_objectArrayType);
p2.Name = "P_1";
methodDef.Parameters.Add(p2);
var body = methodDef.Body;
var processor = body.GetILProcessor();
AddPostInjectMethodBody(processor, postInjectInfo, typeDef, genericTypeDef);
typeDef.Methods.Add(methodDef);
return methodDef;
}
List<MethodDefinition> AddPostInjectMethods(
TypeDefinition typeDef, TypeReference genericTypeDef, ReflectionTypeInfo typeInfo)
{
var postInjectMethods = new List<MethodDefinition>();
for (int i = 0; i < typeInfo.InjectMethods.Count; i++)
{
postInjectMethods.Add(
AddPostInjectMethod(
TypeAnalyzer.ReflectionBakingInjectMethodPrefix + i, typeInfo.InjectMethods[i], typeDef, genericTypeDef));
}
return postInjectMethods;
}
void EmitSetterMethod(
ILProcessor processor, MemberInfo memberInfo, TypeDefinition typeDef, TypeReference genericTypeDef)
{
processor.Emit(OpCodes.Nop);
processor.Emit(OpCodes.Ldarg_0);
processor.Emit(OpCodes.Castclass, genericTypeDef);
processor.Emit(OpCodes.Ldarg_1);
if (memberInfo is FieldInfo)
{
var fieldInfo = (FieldInfo)memberInfo;
EmitCastOperation(processor, fieldInfo.FieldType, typeDef.GenericParameters);
processor.Emit(OpCodes.Stfld, FindLocalField(genericTypeDef, fieldInfo.Name));
}
else
{
var propertyInfo = (PropertyInfo)memberInfo;
EmitCastOperation(processor, propertyInfo.PropertyType, typeDef.GenericParameters);
processor.Emit(OpCodes.Callvirt, FindLocalPropertySetMethod(genericTypeDef, propertyInfo.Name));
}
processor.Emit(OpCodes.Ret);
}
MethodDefinition AddSetterMethod(
string name, MemberInfo memberInfo, TypeDefinition typeDef, TypeReference genericTypeDef)
{
var methodDef = new MethodDefinition(
name,
MethodAttributes.Private | MethodAttributes.HideBySig |
MethodAttributes.Static,
_module.TypeSystem.Void);
var p1 = new ParameterDefinition(_module.TypeSystem.Object);
p1.Name = "P_0";
methodDef.Parameters.Add(p1);
var p2 = new ParameterDefinition(_module.TypeSystem.Object);
p2.Name = "P_1";
methodDef.Parameters.Add(p2);
methodDef.Body.InitLocals = true;
EmitSetterMethod(
methodDef.Body.GetILProcessor(), memberInfo, typeDef, genericTypeDef);
typeDef.Methods.Add(methodDef);
return methodDef;
}
List<MethodDefinition> AddPropertySetters(
TypeDefinition typeDef, TypeReference genericTypeDef, ReflectionTypeInfo typeInfo)
{
var methodDefs = new List<MethodDefinition>();
for (int i = 0; i < typeInfo.InjectProperties.Count; i++)
{
methodDefs.Add(
AddSetterMethod(
TypeAnalyzer.ReflectionBakingPropertySetterPrefix + i,
typeInfo.InjectProperties[i].PropertyInfo, typeDef, genericTypeDef));
}
return methodDefs;
}
List<MethodDefinition> AddFieldSetters(
TypeDefinition typeDef, TypeReference genericTypeDef, ReflectionTypeInfo typeInfo)
{
var methodDefs = new List<MethodDefinition>();
for (int i = 0; i < typeInfo.InjectFields.Count; i++)
{
methodDefs.Add(
AddSetterMethod(
TypeAnalyzer.ReflectionBakingFieldSetterPrefix + i,
typeInfo.InjectFields[i].FieldInfo, typeDef, genericTypeDef));
}
return methodDefs;
}
void CreateGetInfoMethod(
TypeDefinition typeDef, TypeReference genericTypeDef, ReflectionTypeInfo typeInfo,
MethodDefinition factoryMethod, List<MethodDefinition> fieldSetMethods,
List<MethodDefinition> propertySetMethods, List<MethodDefinition> postInjectMethods)
{
var getInfoMethodDef = new MethodDefinition(
TypeAnalyzer.ReflectionBakingGetInjectInfoMethodName,
MethodAttributes.Private | MethodAttributes.HideBySig |
MethodAttributes.Static,
_zenjectTypeInfoType);
typeDef.Methods.Add(getInfoMethodDef);
getInfoMethodDef.CustomAttributes.Add(
new CustomAttribute(_preserveConstructor));
var returnValueVar = new VariableDefinition(_module.TypeSystem.Object);
var body = getInfoMethodDef.Body;
body.Variables.Add(returnValueVar);
body.InitLocals = true;
var instructions = new List<Instruction>();
instructions.Add(Instruction.Create(OpCodes.Ldtoken, genericTypeDef));
instructions.Add(Instruction.Create(OpCodes.Call, _getTypeFromHandleMethod));
if (factoryMethod == null)
{
instructions.Add(Instruction.Create(OpCodes.Ldnull));
}
else
{
instructions.Add(Instruction.Create(OpCodes.Ldnull));
instructions.Add(Instruction.Create(OpCodes.Ldftn, factoryMethod.ChangeDeclaringType(genericTypeDef)));
instructions.Add(Instruction.Create(OpCodes.Newobj, _funcConstructor));
}
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, typeInfo.InjectConstructor.Parameters.Count));
instructions.Add(Instruction.Create(OpCodes.Newarr, _injectableInfoType));
for (int i = 0; i < typeInfo.InjectConstructor.Parameters.Count; i++)
{
var injectableInfo = typeInfo.InjectConstructor.Parameters[i].InjectableInfo;
instructions.Add(Instruction.Create(OpCodes.Dup));
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, i));
EmitNewInjectableInfoInstructions(
instructions, injectableInfo, typeDef);
instructions.Add(Instruction.Create(OpCodes.Stelem_Ref));
}
instructions.Add(Instruction.Create(OpCodes.Newobj, _constructorInfoConstructor));
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, typeInfo.InjectMethods.Count));
instructions.Add(Instruction.Create(OpCodes.Newarr, _injectMethodInfoType));
Assert.IsEqual(postInjectMethods.Count, typeInfo.InjectMethods.Count);
for (int i = 0; i < typeInfo.InjectMethods.Count; i++)
{
var injectMethodInfo = typeInfo.InjectMethods[i];
instructions.Add(Instruction.Create(OpCodes.Dup));
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, i));
AddInjectableMethodInstructions(
instructions, injectMethodInfo, typeDef, genericTypeDef, postInjectMethods[i]);
instructions.Add(Instruction.Create(OpCodes.Stelem_Ref));
}
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, fieldSetMethods.Count + propertySetMethods.Count));
instructions.Add(Instruction.Create(OpCodes.Newarr, _injectMemberInfoType));
for (int i = 0; i < fieldSetMethods.Count; i++)
{
var injectField = typeInfo.InjectFields[i];
instructions.Add(Instruction.Create(OpCodes.Dup));
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, i));
AddInjectableMemberInstructions(
instructions,
injectField.InjectableInfo, injectField.FieldInfo.Name,
typeDef, genericTypeDef, fieldSetMethods[i]);
instructions.Add(Instruction.Create(OpCodes.Stelem_Ref));
}
for (int i = 0; i < propertySetMethods.Count; i++)
{
var injectProperty = typeInfo.InjectProperties[i];
instructions.Add(Instruction.Create(OpCodes.Dup));
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, fieldSetMethods.Count + i));
AddInjectableMemberInstructions(
instructions,
injectProperty.InjectableInfo,
injectProperty.PropertyInfo.Name, typeDef, genericTypeDef,
propertySetMethods[i]);
instructions.Add(Instruction.Create(OpCodes.Stelem_Ref));
}
instructions.Add(Instruction.Create(OpCodes.Newobj, _zenjectTypeInfoConstructor));
instructions.Add(Instruction.Create(OpCodes.Stloc_0));
instructions.Add(Instruction.Create(OpCodes.Ldloc_S, returnValueVar));
instructions.Add(Instruction.Create(OpCodes.Ret));
var processor = body.GetILProcessor();
foreach (var instruction in instructions)
{
processor.Append(instruction);
}
}
MethodReference FindLocalPropertySetMethod(
TypeReference specificTypeRef, string memberName)
{
foreach (var typeRef in specificTypeRef.GetSpecificBaseTypesAndSelf())
{
var candidatePropertyDef = typeRef.Resolve().Properties
.Where(x => x.Name == memberName).SingleOrDefault();
if (candidatePropertyDef != null)
{
return candidatePropertyDef.SetMethod.ChangeDeclaringType(typeRef);
}
}
throw Assert.CreateException();
}
FieldReference FindLocalField(
TypeReference specificTypeRef, string fieldName)
{
foreach (var typeRef in specificTypeRef.GetSpecificBaseTypesAndSelf())
{
var candidateFieldDef = typeRef.Resolve().Fields
.Where(x => x.Name == fieldName).SingleOrDefault();
if (candidateFieldDef != null)
{
return candidateFieldDef.ChangeDeclaringType(typeRef);
}
}
throw Assert.CreateException();
}
bool TryFindLocalMethod(
TypeReference specificTypeRef, string methodName, out TypeReference declaringTypeRef, out MethodReference methodRef)
{
foreach (var typeRef in specificTypeRef.GetSpecificBaseTypesAndSelf())
{
var candidateMethodDef = typeRef.Resolve().Methods
.Where(x => x.Name == methodName).SingleOrDefault();
if (candidateMethodDef != null)
{
declaringTypeRef = typeRef;
methodRef = candidateMethodDef.ChangeDeclaringType(typeRef);
return true;
}
}
declaringTypeRef = null;
methodRef = null;
return false;
}
void AddObjectInstructions(
List<Instruction> instructions,
object identifier)
{
if (identifier == null)
{
instructions.Add(Instruction.Create(OpCodes.Ldnull));
}
else if (identifier is string)
{
instructions.Add(Instruction.Create(OpCodes.Ldstr, (string)identifier));
}
else if (identifier is int)
{
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, (int)identifier));
instructions.Add(Instruction.Create(OpCodes.Box, _module.Import(typeof(int))));
}
else if (identifier.GetType().IsEnum)
{
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, (int)identifier));
instructions.Add(Instruction.Create(OpCodes.Box, _module.Import(identifier.GetType())));
}
else
{
throw Assert.CreateException(
"Cannot process values with type '{0}' currently. Feel free to add support for this and submit a pull request to github.", identifier.GetType());
}
}
TypeReference CreateGenericInstanceIfNecessary(
Type memberType, Collection<GenericParameter> genericParams)
{
if (!memberType.ContainsGenericParameters)
{
return _module.Import(memberType);
}
if (memberType.IsGenericParameter)
{
return genericParams[memberType.GenericParameterPosition];
}
if (memberType.IsArray)
{
return new ArrayType(
CreateGenericInstanceIfNecessary(memberType.GetElementType(), genericParams), memberType.GetArrayRank());
}
var genericMemberType = memberType.GetGenericTypeDefinition();
var genericInstance = new GenericInstanceType(_module.Import(genericMemberType));
foreach (var arg in memberType.GenericArguments())
{
genericInstance.GenericArguments.Add(
CreateGenericInstanceIfNecessary(arg, genericParams));
}
return genericInstance;
}
void AddInjectableMemberInstructions(
List<Instruction> instructions,
InjectableInfo injectableInfo, string name,
TypeDefinition typeDef, TypeReference genericTypeDef,
MethodDefinition methodDef)
{
instructions.Add(Instruction.Create(OpCodes.Ldnull));
instructions.Add(Instruction.Create(OpCodes.Ldftn, methodDef.ChangeDeclaringType(genericTypeDef)));
instructions.Add(Instruction.Create(OpCodes.Newobj, _funcMemberSetter));
EmitNewInjectableInfoInstructions(
instructions, injectableInfo, typeDef);
instructions.Add(Instruction.Create(OpCodes.Newobj, _injectMemberInfoConstructor));
}
void AddInjectableMethodInstructions(
List<Instruction> instructions,
ReflectionTypeInfo.InjectMethodInfo injectMethod,
TypeDefinition typeDef, TypeReference genericTypeDef,
MethodDefinition methodDef)
{
instructions.Add(Instruction.Create(OpCodes.Ldnull));
instructions.Add(Instruction.Create(OpCodes.Ldftn, methodDef.ChangeDeclaringType(genericTypeDef)));
instructions.Add(Instruction.Create(OpCodes.Newobj, _funcPostInject));
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, injectMethod.Parameters.Count));
instructions.Add(Instruction.Create(OpCodes.Newarr, _injectableInfoType));
for (int i = 0; i < injectMethod.Parameters.Count; i++)
{
var injectableInfo = injectMethod.Parameters[i].InjectableInfo;
instructions.Add(Instruction.Create(OpCodes.Dup));
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, i));
EmitNewInjectableInfoInstructions(
instructions, injectableInfo, typeDef);
instructions.Add(Instruction.Create(OpCodes.Stelem_Ref));
}
instructions.Add(Instruction.Create(OpCodes.Ldstr, injectMethod.MethodInfo.Name));
instructions.Add(Instruction.Create(OpCodes.Newobj, _injectMethodInfoConstructor));
}
void EmitNewInjectableInfoInstructions(
List<Instruction> instructions,
InjectableInfo injectableInfo,
TypeDefinition typeDef)
{
if (injectableInfo.Optional)
{
instructions.Add(Instruction.Create(OpCodes.Ldc_I4_1));
}
else
{
instructions.Add(Instruction.Create(OpCodes.Ldc_I4_0));
}
AddObjectInstructions(instructions, injectableInfo.Identifier);
instructions.Add(Instruction.Create(OpCodes.Ldstr, injectableInfo.MemberName));
instructions.Add(Instruction.Create(OpCodes.Ldtoken, CreateGenericInstanceIfNecessary(injectableInfo.MemberType, typeDef.GenericParameters)));
instructions.Add(Instruction.Create(OpCodes.Call, _getTypeFromHandleMethod));
AddObjectInstructions(instructions, injectableInfo.DefaultValue);
instructions.Add(Instruction.Create(OpCodes.Ldc_I4, (int)injectableInfo.SourceType));
instructions.Add(Instruction.Create(OpCodes.Newobj, _injectableInfoConstructor));
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: a664c0011937115449c81d8ca4a2f6c7
timeCreated: 1538185954
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3879d05eafe89b844a5fc0db8cfd9c55
folderAsset: yes
timeCreated: 1537245053
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 6b309800e744d8c46ad868763fc9c429
timeCreated: 1538196675
licenseType: Pro
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: b6433e8939bdf284693b7fa9b719bfcd
timeCreated: 1538196675
licenseType: Pro
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 58ca997f0a3dfb84590febf580194214
timeCreated: 1538196674
licenseType: Pro
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 0fdc9d5333ed94347bd076c3946dd19d
timeCreated: 1538196673
licenseType: Pro
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: bdf7617b0450e55498cedcfc70529ff5
folderAsset: yes
timeCreated: 1537245054
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ModestTree;
using UnityEditorInternal;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
public class AssemblyPathRegistry
{
static List<string> _assemblies;
public static List<string> GetAllGeneratedAssemblyRelativePaths()
{
if (_assemblies == null)
{
_assemblies = LookupAllGeneratedAssemblyPaths();
Assert.IsNotNull(_assemblies);
}
return _assemblies;
}
static bool IsManagedAssembly(string systemPath)
{
DllType dllType = InternalEditorUtility.DetectDotNetDll(systemPath);
return dllType != DllType.Unknown && dllType != DllType.Native;
}
static List<string> LookupAllGeneratedAssemblyPaths()
{
var assemblies = new List<string>(20);
// We could also add the ones in the project but we probably don't want to edit those
//FindAssemblies(Application.dataPath, 120, assemblies);
FindAssemblies(Application.dataPath + "/../Library/ScriptAssemblies/", 2, assemblies);
return assemblies;
}
public static void FindAssemblies(string systemPath, int maxDepth, List<string> result)
{
if (maxDepth > 0)
{
if (Directory.Exists(systemPath))
{
var dirInfo = new DirectoryInfo(systemPath);
result.AddRange(
dirInfo.GetFiles().Select(x => x.FullName)
.Where(IsManagedAssembly)
.Select(ReflectionBakingInternalUtil.ConvertAbsoluteToAssetPath));
var directories = dirInfo.GetDirectories();
for (int i = 0; i < directories.Length; i++)
{
DirectoryInfo current = directories[i];
FindAssemblies(current.FullName, maxDepth - 1, result);
}
}
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: f96372c95411c904bb55ba67b55e0c84
timeCreated: 1537003252
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,107 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using ModestTree;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
using Zenject.ReflectionBaking.Mono.Cecil;
using Debug = UnityEngine.Debug;
namespace Zenject.ReflectionBaking
{
public static class ReflectionBakingBuildObserver
{
[InitializeOnLoadMethod]
public static void Initialize()
{
CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompiled;
}
static void OnAssemblyCompiled(string assemblyAssetPath, CompilerMessage[] messages)
{
#if !UNITY_2018_1_OR_NEWER
if (Application.isEditor && !BuildPipeline.isBuildingPlayer)
{
return;
}
#endif
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WSAPlayer)
{
Log.Warn("Zenject reflection baking skipped because it is not currently supported on WSA platform!");
}
else
{
TryWeaveAssembly(assemblyAssetPath);
}
}
static void TryWeaveAssembly(string assemblyAssetPath)
{
var settings = ReflectionBakingInternalUtil.TryGetEnabledSettingsInstance();
if (settings == null)
{
return;
}
if (settings.AllGeneratedAssemblies && settings.ExcludeAssemblies.Contains(assemblyAssetPath))
{
return;
}
if (!settings.AllGeneratedAssemblies && !settings.IncludeAssemblies.Contains(assemblyAssetPath))
{
return;
}
var stopwatch = new Stopwatch();
stopwatch.Start();
var assemblyFullPath = ReflectionBakingInternalUtil.ConvertAssetPathToSystemPath(assemblyAssetPath);
var readerParameters = new ReaderParameters
{
AssemblyResolver = new UnityAssemblyResolver(),
// Is this necessary?
//ReadSymbols = true,
};
var module = ModuleDefinition.ReadModule(assemblyFullPath, readerParameters);
var assemblyRefNames = module.AssemblyReferences.Select(x => x.Name.ToLower()).ToList();
if (!assemblyRefNames.Contains("zenject-usage"))
{
// Zenject-usage is used by the generated methods
// Important that we do this check otherwise we can corrupt some dlls that don't have access to it
return;
}
var assemblyName = Path.GetFileNameWithoutExtension(assemblyAssetPath);
var assembly = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.GetName().Name == assemblyName).OnlyOrDefault();
Assert.IsNotNull(assembly, "Could not find unique assembly '{0}' in currently loaded list of assemblies", assemblyName);
int numTypesChanged = ReflectionBakingModuleEditor.WeaveAssembly(
module, assembly, settings.NamespacePatterns);
if (numTypesChanged > 0)
{
var writerParams = new WriterParameters()
{
// Is this necessary?
//WriteSymbols = true
};
module.Write(assemblyFullPath, writerParams);
Debug.Log("Added reflection baking to '{0}' types in assembly '{1}', took {2:0.00} seconds"
.Fmt(numTypesChanged, Path.GetFileName(assemblyAssetPath), stopwatch.Elapsed.TotalSeconds));
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 374dbffd3e3c6504489ada7d14aa4006
timeCreated: 1537501691
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,78 @@
using System;
using System.IO;
using System.Reflection;
using ModestTree;
using UnityEditor;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
public static class ReflectionBakingInternalUtil
{
public static string ConvertAssetPathToSystemPath(string assetPath)
{
string path = Application.dataPath;
int pathLength = path.Length;
path = path.Substring(0, pathLength - /* Assets */ 6);
path = Path.Combine(path, assetPath);
return path;
}
public static ZenjectReflectionBakingSettings TryGetEnabledSettingsInstance()
{
string[] guids = AssetDatabase.FindAssets("t:ZenjectReflectionBakingSettings");
if (guids.IsEmpty())
{
return null;
}
ZenjectReflectionBakingSettings enabledSettings = null;
foreach (var guid in guids)
{
var candidate = AssetDatabase.LoadAssetAtPath<ZenjectReflectionBakingSettings>(
AssetDatabase.GUIDToAssetPath(guid));
if ((Application.isEditor && candidate.IsEnabledInEditor) || (BuildPipeline.isBuildingPlayer && candidate.IsEnabledInBuilds))
{
Assert.IsNull(enabledSettings, "Found multiple enabled ZenjectReflectionBakingSettings objects! Please disable/delete one to continue.");
enabledSettings = candidate;
}
}
return enabledSettings;
}
public static string ConvertAbsoluteToAssetPath(string systemPath)
{
var projectPath = Application.dataPath;
// Remove 'Assets'
projectPath = projectPath.Substring(0, projectPath.Length - /* Assets */ 6);
int systemPathLength = systemPath.Length;
int assetPathLength = systemPathLength - projectPath.Length;
Assert.That(assetPathLength > 0, "Unexpect path '{0}'", systemPath);
return systemPath.Substring(projectPath.Length, assetPathLength);
}
public static void TryForceUnityFullCompile()
{
Type compInterface = typeof(UnityEditor.Editor).Assembly.GetType(
"UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface");
if (compInterface != null)
{
var dirtyAllScriptsMethod = compInterface.GetMethod(
"DirtyAllScripts", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
dirtyAllScriptsMethod.Invoke(null, null);
}
UnityEditor.AssetDatabase.Refresh();
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 68724c9557073844fb7c3f088c588d32
timeCreated: 1537003252
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,24 @@
#if !NOT_UNITY3D
using System.IO;
using UnityEditor;
using UnityEngine;
using Zenject.Internal;
namespace Zenject.ReflectionBaking
{
public static class ReflectionBakingMenuItems
{
[MenuItem("Assets/Create/Zenject/Reflection Baking Settings", false, 100)]
public static void CreateReflectionBakingSettings()
{
var folderPath = ZenUnityEditorUtil.GetCurrentDirectoryAssetPathFromSelection();
var config = ScriptableObject.CreateInstance<ZenjectReflectionBakingSettings>();
ZenUnityEditorUtil.SaveScriptableObjectAsset(
Path.Combine(folderPath, "ZenjectReflectionBakingSettings.asset"), config);
}
}
}
#endif
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 549215a3ba27806449b2b1542fdffc03
timeCreated: 1537690031
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Zenject.ReflectionBaking.Mono.Cecil;
namespace Zenject.ReflectionBaking
{
public class UnityAssemblyResolver : BaseAssemblyResolver
{
readonly IDictionary<string, string> _appDomainAssemblyLocations;
readonly IDictionary<string, AssemblyDefinition> _cache;
public UnityAssemblyResolver()
{
_appDomainAssemblyLocations = new Dictionary<string, string>();
_cache = new Dictionary<string, AssemblyDefinition>();
AppDomain domain = AppDomain.CurrentDomain;
Assembly[] assemblies = domain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
#if NET_4_6
if (assemblies[i].IsDynamic)
{
continue;
}
#endif
_appDomainAssemblyLocations[assemblies[i].FullName] = assemblies[i].Location;
AddSearchDirectory(Path.GetDirectoryName(assemblies[i].Location));
}
}
public override AssemblyDefinition Resolve(AssemblyNameReference name)
{
AssemblyDefinition assemblyDef = FindAssemblyDefinition(name.FullName, null);
if (assemblyDef == null)
{
assemblyDef = base.Resolve(name);
_cache[name.FullName] = assemblyDef;
}
return assemblyDef;
}
public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
AssemblyDefinition assemblyDef = FindAssemblyDefinition(name.FullName, parameters);
if (assemblyDef == null)
{
assemblyDef = base.Resolve(name, parameters);
_cache[name.FullName] = assemblyDef;
}
return assemblyDef;
}
/// Searches for AssemblyDefinition in our cache, and failing that,
/// looks for a known location. Returns null if both attempts fail.
AssemblyDefinition FindAssemblyDefinition(string fullName, ReaderParameters parameters)
{
if (fullName == null)
{
throw new ArgumentNullException("fullName");
}
AssemblyDefinition assemblyDefinition;
// Look in cache first
if (_cache.TryGetValue(fullName, out assemblyDefinition))
{
return assemblyDefinition;
}
// Try to use known location
string location;
if (_appDomainAssemblyLocations.TryGetValue(fullName, out location))
{
if (parameters != null)
{
assemblyDefinition = AssemblyDefinition.ReadAssembly(location, parameters);
}
else
{
assemblyDefinition = AssemblyDefinition.ReadAssembly(location);
}
_cache[fullName] = assemblyDefinition;
return assemblyDefinition;
}
return null;
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b107233111f831043b3d5983fe6f1b25
timeCreated: 1537934945
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,56 @@
using System.Collections.Generic;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
public class ZenjectReflectionBakingSettings : ScriptableObject
{
[SerializeField]
bool _isEnabledInBuilds = true;
[SerializeField]
bool _isEnabledInEditor = false;
[SerializeField]
bool _allGeneratedAssemblies = true;
[SerializeField]
List<string> _includeAssemblies = null;
[SerializeField]
List<string> _excludeAssemblies = null;
[SerializeField]
List<string> _namespacePatterns = null;
public List<string> NamespacePatterns
{
get { return _namespacePatterns; }
}
public List<string> IncludeAssemblies
{
get { return _includeAssemblies; }
}
public List<string> ExcludeAssemblies
{
get { return _excludeAssemblies; }
}
public bool IsEnabledInEditor
{
get { return _isEnabledInEditor; }
}
public bool IsEnabledInBuilds
{
get { return _isEnabledInBuilds; }
}
public bool AllGeneratedAssemblies
{
get { return _allGeneratedAssemblies; }
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 1ab372d6a005c8344b5d6b25dbc310ce
timeCreated: 1536333743
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,236 @@
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace Zenject.ReflectionBaking
{
[CustomEditor(typeof(ZenjectReflectionBakingSettings))]
public class ZenjectReflectionBakingSettingsEditor : Editor
{
SerializedProperty _includeAssemblies;
SerializedProperty _excludeAssemblies;
SerializedProperty _namespacePatterns;
SerializedProperty _isEnabledInBuilds;
SerializedProperty _isEnabledInEditor;
SerializedProperty _allGeneratedAssemblies;
// Lists
ReorderableList _includeAssembliesList;
ReorderableList _excludeAssembliesList;
ReorderableList _namespacePatternsList;
// Layouts
Vector2 _logScrollPosition;
int _selectedLogIndex;
bool _hasModifiedProperties;
static GUIContent _includeAssembliesListHeaderContent = new GUIContent
{
text = "Include Assemblies",
tooltip = "The list of all the assemblies that will be editted to have reflection information directly embedded"
};
static GUIContent _excludeAssembliesListHeaderContent = new GUIContent
{
text = "Exclude Assemblies",
tooltip = "The list of all the assemblies that will not be editted"
};
static GUIContent _namespacePatternListHeaderContent = new GUIContent
{
text = "Namespace Patterns",
tooltip = "This list of Regex patterns will be compared to the name of each type in the given assemblies, and when a match is found that type will be editting to directly contain reflection information"
};
void OnEnable()
{
_includeAssemblies = serializedObject.FindProperty("_includeAssemblies");
_excludeAssemblies = serializedObject.FindProperty("_excludeAssemblies");
_namespacePatterns = serializedObject.FindProperty("_namespacePatterns");
_isEnabledInEditor = serializedObject.FindProperty("_isEnabledInEditor");
_isEnabledInBuilds = serializedObject.FindProperty("_isEnabledInBuilds");
_allGeneratedAssemblies = serializedObject.FindProperty("_allGeneratedAssemblies");
_namespacePatternsList = new ReorderableList(serializedObject, _namespacePatterns);
_namespacePatternsList.drawHeaderCallback += OnNamespacePatternsDrawHeader;
_namespacePatternsList.drawElementCallback += OnNamespacePatternsDrawElement;
_includeAssembliesList = new ReorderableList(serializedObject, _includeAssemblies);
_includeAssembliesList.drawHeaderCallback += OnIncludeWeavedAssemblyDrawHeader;
_includeAssembliesList.onAddCallback += OnIncludeWeavedAssemblyElementAdded;
_includeAssembliesList.drawElementCallback += OnIncludeAssemblyListDrawElement;
_excludeAssembliesList = new ReorderableList(serializedObject, _excludeAssemblies);
_excludeAssembliesList.drawHeaderCallback += OnExcludeWeavedAssemblyDrawHeader;
_excludeAssembliesList.onAddCallback += OnExcludeWeavedAssemblyElementAdded;
_excludeAssembliesList.drawElementCallback += OnExcludeAssemblyListDrawElement;
}
void OnNamespacePatternsDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty indexProperty = _namespacePatterns.GetArrayElementAtIndex(index);
indexProperty.stringValue = EditorGUI.TextField(rect, indexProperty.stringValue);
}
void OnExcludeAssemblyListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty indexProperty = _excludeAssemblies.GetArrayElementAtIndex(index);
EditorGUI.LabelField(rect, indexProperty.stringValue, EditorStyles.textArea);
}
void OnIncludeAssemblyListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty indexProperty = _includeAssemblies.GetArrayElementAtIndex(index);
EditorGUI.LabelField(rect, indexProperty.stringValue, EditorStyles.textArea);
}
void OnNamespacePatternsDrawHeader(Rect rect)
{
GUI.Label(rect, _namespacePatternListHeaderContent);
}
void OnExcludeWeavedAssemblyDrawHeader(Rect rect)
{
GUI.Label(rect, _excludeAssembliesListHeaderContent);
}
void OnIncludeWeavedAssemblyDrawHeader(Rect rect)
{
GUI.Label(rect, _includeAssembliesListHeaderContent);
}
public override void OnInspectorGUI()
{
EditorGUI.BeginChangeCheck();
{
GUILayout.Label("Settings", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_isEnabledInBuilds, true);
var oldIsEnabledInEditorValue = _isEnabledInEditor.boolValue;
EditorGUILayout.PropertyField(_isEnabledInEditor, true);
if (oldIsEnabledInEditorValue != _isEnabledInEditor.boolValue)
{
ReflectionBakingInternalUtil.TryForceUnityFullCompile();
}
#if !UNITY_2018_1_OR_NEWER
if (_isEnabledInEditor.boolValue)
{
EditorGUILayout.HelpBox(
"Reflection baking inside unity editor requires Unity 2018+! It is however supported for builds", MessageType.Error);
}
#endif
EditorGUILayout.PropertyField(_allGeneratedAssemblies, true);
if (_allGeneratedAssemblies.boolValue)
{
_excludeAssembliesList.DoLayoutList();
GUI.enabled = false;
try
{
_includeAssembliesList.DoLayoutList();
}
finally
{
GUI.enabled = true;
}
}
else
{
GUI.enabled = false;
try
{
_excludeAssembliesList.DoLayoutList();
}
finally
{
GUI.enabled = true;
}
_includeAssembliesList.DoLayoutList();
}
_namespacePatternsList.DoLayoutList();
}
if (EditorGUI.EndChangeCheck())
{
_hasModifiedProperties = true;
}
if (_hasModifiedProperties)
{
_hasModifiedProperties = false;
ApplyModifiedProperties();
}
}
void ApplyModifiedProperties()
{
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
}
void OnExcludeWeavedAssemblyElementAdded(ReorderableList list)
{
OnAssemblyElementAdded(_excludeAssemblies, list);
}
void OnIncludeWeavedAssemblyElementAdded(ReorderableList list)
{
OnAssemblyElementAdded(_includeAssemblies, list);
}
void OnAssemblyElementAdded(SerializedProperty listProperty, ReorderableList list)
{
GenericMenu menu = new GenericMenu();
var paths = AssemblyPathRegistry.GetAllGeneratedAssemblyRelativePaths();
for (int i = 0; i < paths.Count; i++)
{
var path = paths[i];
bool foundMatch = false;
for (int k = 0; k < listProperty.arraySize; k++)
{
SerializedProperty current = listProperty.GetArrayElementAtIndex(k);
if (path == current.stringValue)
{
foundMatch = true;
break;
}
}
if (!foundMatch)
{
GUIContent content = new GUIContent(path);
menu.AddItem(content, false, p => OnWeavedAssemblyAdded(listProperty, p), path);
}
}
if (menu.GetItemCount() == 0)
{
menu.AddDisabledItem(new GUIContent("[All Assemblies Added]"));
}
menu.ShowAsContext();
}
void OnWeavedAssemblyAdded(SerializedProperty listProperty, object path)
{
listProperty.arraySize++;
SerializedProperty weaved = listProperty.GetArrayElementAtIndex(listProperty.arraySize - 1);
weaved.stringValue = ((string)path).Replace("\\", "/");
ApplyModifiedProperties();
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 90683e755a104ed4ab5841ef7bb58742
timeCreated: 1538185954
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
{
"name": "Zenject-ReflectionBaking-Editor",
"references": [
"Zenject",
"Zenject-Editor"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": []
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 14f8b558cd941e545961d1d8d31254f0
timeCreated: 1536994295
licenseType: Free
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: