public static TypeReference SubstituteGenericParameters( this GenericInstanceType @this, IReadOnlyCollection <GenericParameter> genericParameters, ModuleDefinition moduleDefinition) { var genericType = moduleDefinition.ImportReference(@this.Resolve()); Debug.Assert(genericType.GenericParameters.Count == @this.GenericArguments.Count); var substitutedGenericParameters = Enumerable .Range(0, genericType.GenericParameters.Count) .Select(i => { var argument = @this.GenericArguments[i]; if (argument.IsGenericParameter) { Debug.Assert(genericParameters.Any(gp => gp.FullName == argument.FullName)); return(genericParameters.Single(gp => gp.FullName == argument.FullName)); } if (argument is ArrayType arrayType) { return(arrayType.SubstituteGenericParameters(genericParameters, moduleDefinition)); } if (argument.IsGenericInstance && argument is GenericInstanceType genericInstanceType) { return(SubstituteGenericParameters(genericInstanceType, genericParameters, moduleDefinition)); } return(argument); }) .ToArray(); return(genericType.MakeGenericInstanceType(substitutedGenericParameters)); }
private static TypeDefinition ResolveImpl(this TypeReference reference) { try { if (reference.IsGenericInstance) { var previous_instance = (GenericInstanceType)reference; var instance = new GenericInstanceType(previous_instance.ElementType.SmartResolve()); foreach (var argument in previous_instance.GenericArguments) { instance.GenericArguments.Add(argument.SmartResolve()); } return(instance.Resolve()); } return(reference.Resolve()); } catch (AssemblyResolutionException ex) { return(null); } catch (Exception ex) { return(null); } }
public static GenericInstanceType InflateType(GenericContext context, GenericInstanceType genericInstanceType) { var inflatedType = ConstructGenericType(context, genericInstanceType.Resolve(), genericInstanceType.GenericArguments); inflatedType.MetadataToken = genericInstanceType.MetadataToken; return(inflatedType); }
private static void AddArrayIfNeeded(GenericInstanceType type, InflatedCollectionCollector generics, GenericInstanceMethod contextMethod, TypeDefinition ienumerableDefinition, TypeDefinition icollectionDefinition, TypeDefinition ilistDefinition) { TypeDefinition definition = type.Resolve(); if (((definition == ienumerableDefinition) || (definition == icollectionDefinition)) || (definition == ilistDefinition)) { ProcessArray(new ArrayType(type.GenericArguments[0]), generics, new GenericContext(type, contextMethod)); } }
private TypeReference ParametrizeSubInterface(GenericInstanceType interfaceType, TypeReference typeReference) { var gparams = interfaceType.GenericArguments .Select(tr => tr is GenericParameter gp ? _target.Module.ImportReference(((GenericInstanceType)typeReference).GenericArguments[gp.Position]) : tr) .ToArray(); return(_target.Module.ImportReference(interfaceType.Resolve()).MakeGenericInstanceType(gparams)); }
public static TypeReference ResolveGenericParameters(this TypeReference type, GenericInstanceMethod?methodInstance, GenericInstanceType?typeInstance) { if (type is GenericParameter genericParameter) { switch (genericParameter.Owner) { case MethodReference ownerMethod: { if (ownerMethod.Resolve() != methodInstance?.Resolve()) { throw new NotSupportedException($"Generic parameter {type} comes from method {ownerMethod} which is different from provided {methodInstance}."); } return(methodInstance.GenericArguments[genericParameter.Position].ResolveGenericParameters(methodInstance, typeInstance)); } case TypeReference ownerType: { if (ownerType.Resolve() != typeInstance?.Resolve()) { throw new NotSupportedException($"Generic parameter {type} comes from type {ownerType} which is different from provided {typeInstance}."); } return(typeInstance.GenericArguments[genericParameter.Position].ResolveGenericParameters(methodInstance, typeInstance)); } default: throw new NotSupportedException($"Unsupported generic parameter owner: {genericParameter.Owner}."); } } if (type is GenericInstanceType generic) { var changed = (GenericInstanceType?)null; for (var i = 0; i < generic.GenericArguments.Count; i++) { var argument = generic.GenericArguments[i]; var resolved = argument.ResolveGenericParameters(methodInstance, typeInstance); if (resolved != argument) { changed = changed ?? Clone(generic); changed.GenericArguments[i] = resolved; } } return(changed ?? type); } if (type is ByReferenceType reference) { var resolved = reference.ElementType.ResolveGenericParameters(methodInstance, typeInstance); if (resolved == reference.ElementType) { return(type); } return(new ByReferenceType(resolved)); } return(type); }
public static GenericInstanceType ParametrizeGenericInstance(this MemberReference member, GenericInstanceType generic) { if (!generic.ContainsGenericParameter) { return(generic); } var args = generic.GenericArguments.Select(ga => member.ResolveIfGeneric(ga)).ToArray(); return(generic.Resolve().MakeGenericInstanceType(args)); }
public void AddGenericInstance(GenericInstanceType ty) { if (genericInstances.ContainsKey(ty.FullName)) { return; } genericInstances.Add(ty.FullName, ty); // recursively add generic arguments foreach (var arg in ty.GenericArguments) { if (arg.IsGenericInstance) { AddGenericInstance((GenericInstanceType)arg); } } // build mapping from generic parameter names to instantiated types TypeDefinition def = ty.Resolve(); var genericParameterMap = new Dictionary <string, TypeReference>(); for (int i = 0; i < def.GenericParameters.Count; i++) { genericParameterMap.Add(def.GenericParameters[i].FullName, ty.GenericArguments[i]); } // recursively add implemented interfaces foreach (var intf in def.Interfaces.Select(i => i.InterfaceType).Where(i => i.ContainsGenericParameter && i is GenericInstanceType).Cast <GenericInstanceType>()) { var type = TypeHelpers.InstantiateType(intf, genericParameterMap); if (type is GenericInstanceType) { AddGenericInstance(type as GenericInstanceType); } } // recursively add other instances introduced by function parameters foreach (var m in def.Methods) { foreach (GenericInstanceType pty in m.Parameters .Select(p => p.ParameterType) .Concat(Enumerable.Repeat(m.ReturnType, 1)) .Where(t => t.ContainsGenericParameter && t is GenericInstanceType) .Cast <GenericInstanceType>()) { var type = TypeHelpers.InstantiateType(pty, genericParameterMap); if (type is GenericInstanceType) { AddGenericInstance(type as GenericInstanceType); } } } }
private IEnumerable <Instruction> CastsToSupportedCollections(MethodBody body) { return(InstrumentationUtil.Where(body, delegate(Instruction candidate) { if (candidate.OpCode != OpCodes.Castclass) { return false; } GenericInstanceType target = candidate.Operand as GenericInstanceType; return target != null && HasReplacement(target.Resolve().FullName); })); }
public EmittedTypeDefinition(string name, string parentType, GenericInstanceType type) { Name = name; ParentType = parentType; var typeDef = type.Resolve(); Properties = typeDef .Properties .Zip(type.GenericArguments) .Select(x => new EmittedTypeProperty(x.Item1.Name, x.Item2.Resolve())) .ToArray(); }
public static MethodReference MakeGenericInstanceConstructor(this GenericInstanceType @this) { var resolvedType = @this.Resolve().GetConstructors().Single(); var result = new MethodReference(resolvedType.Name, resolvedType.ReturnType, @this) { HasThis = resolvedType.HasThis, ExplicitThis = resolvedType.ExplicitThis, CallingConvention = resolvedType.CallingConvention }; result.Parameters.AddRange(resolvedType.Parameters.Select(parameter => new ParameterDefinition(parameter.ParameterType))); result.GenericParameters.AddRange(resolvedType.GenericParameters.Select(parameter => new GenericParameter(parameter.Name, result))); return(result); }
private TypeReference ParametrizeSubInterface(GenericInstanceType interfaceType, TypeReference typeReference) { TypeReference LookupType(TypeReference tr) { if (tr is GenericParameter gp) { return(((GenericInstanceType)typeReference).GenericArguments[gp.Position]); } return(tr); } var gparams = interfaceType.GenericArguments.Select(LookupType).ToArray(); return(interfaceType.Resolve().MakeGenericInstanceType(gparams)); }
public Type Resolve(TypeReference type, GenericBindingContext bindingContext) { ITypeContainer container = _moduleResolver.Resolve(type.Scope); GenericInstanceType genericInstanceType = type as GenericInstanceType; if (genericInstanceType != null) { Type genericType = Resolve(genericInstanceType.Resolve()); Type[] genericArguments = genericInstanceType.GenericArguments .Select(bindingContext.Resolve) .Select(argument => Resolve(argument, bindingContext)).ToArray(); return(genericType.MakeGenericType(genericArguments)); } return(container.GetType(type.FullName)); }
/// <summary> /// Takes generic argments from child class and applies them to base class /// <br/> /// eg makes `Base{T}` in <c>Child{int} : Base{int}</c> have `int` instead of `T` /// </summary> /// <param name="parentReference"></param> /// <param name="childReference"></param> /// <returns></returns> public static GenericInstanceType MatchGenericParameters(this GenericInstanceType parentReference, TypeReference childReference) { if (!parentReference.IsGenericInstance) { throw new InvalidOperationException("Can't make non generic type into generic"); } // make new type so we can replace the args on it // resolve it so we have non-generic instance (eg just instance with <T> instead of <int>) // if we dont cecil will make it double generic (eg INVALID IL) var generic = new GenericInstanceType(parentReference.Resolve()); foreach (var arg in parentReference.GenericArguments) { generic.GenericArguments.Add(arg); } for (var i = 0; i < generic.GenericArguments.Count; i++) { // if arg is not generic // eg List<int> would be int so not generic. // But List<T> would be T so is generic if (!generic.GenericArguments[i].IsGenericParameter) { continue; } // get the generic name, eg T var name = generic.GenericArguments[i].Name; // find what type T is, eg turn it into `int` if `List<int>` var arg = FindMatchingGenericArgument(childReference, name); // import just to be safe var imported = parentReference.Module.ImportReference(arg); // set arg on generic, parent ref will be Base<int> instead of just Base<T> generic.GenericArguments[i] = imported; } return(generic); }
public override TypeReference Visit(GenericParameter type) { if (type.Type == GenericParameterType.Method) { if (genericContextMethod != null && type.Position < genericContextMethod.GenericArguments.Count) { // Look for generic parameter in both resolved and element method var genericContext1 = genericContextMethod.ElementMethod; var genericContext2 = genericContextMethod.Resolve(); var genericParameter1 = genericContext1.GenericParameters[type.Position]; var genericParameter2 = genericContext2.GenericParameters[type.Position]; if (resolveOnlyReferences) { if (genericParameter1.Name == type.Name) { return(genericParameter2); } } else { if (genericParameter1.Name == type.Name) { return(genericContextMethod.GenericArguments[type.Position]); } if (genericParameter2.Name == type.Name) { return(genericContextMethod.GenericArguments[type.Position]); } } } } else { if (genericContextType != null && type.Position < genericContextType.GenericArguments.Count) { // Look for generic parameter in both resolved and element method var genericContext1 = genericContextType.ElementType; var genericContext2 = genericContextType.Resolve(); var genericParameter1 = genericContext1.GenericParameters[type.Position]; var genericParameter2 = genericContext2.GenericParameters[type.Position]; if (resolveOnlyReferences) { if (genericParameter1.Name == type.Name) { return(genericParameter2); } } else { if (genericParameter1.Name == type.Name) { return(genericContextType.GenericArguments[type.Position]); } if (genericParameter2.Name == type.Name) { return(genericContextType.GenericArguments[type.Position]); } } } } return(base.Visit(type)); }
void DecorateMethod(MethodDefinition playableMethod, MethodDefinition originalMethod, TypeDefinition requestIdentifier, TypeDefinition responseIdentifier) { var reqResTypes = new List <TypeReference>(); foreach (var pType in playableMethod.Parameters) { var module = GetModuleForReferencedType(pType.ParameterType); var def = module.ImportReference(pType.ParameterType); reqResTypes.Add(ModuleDefinition.ImportReference(def.Resolve())); } var resModule = GetModuleForReferencedType(playableMethod.ReturnType); var responseType = ModuleDefinition.ImportReference(resModule.ImportReference(playableMethod.ReturnType).Resolve()); bool isFunc = responseType.FullName != "System.Void"; //this is to determine if original method is a function or an action if (isFunc) { reqResTypes.Add(responseType); } var reqResArray = reqResTypes.ToArray(); var dynPlayerTypeDef = TestFlaskAspectsModule.GetType(GetPlayerType(playableMethod.Parameters.Count, isFunc).FullName); var dynPlayerTypeRef = ModuleDefinition.ImportReference(dynPlayerTypeDef); TypeDefinition playerTypeDef; TypeReference playerTypeRef; bool isPlayerGeneric = isFunc || playableMethod.Parameters.Count > 0; //if the player is instance is generic somehow (usually it is) if (isPlayerGeneric) { playerTypeRef = dynPlayerTypeRef.MakeGenericInstanceType(reqResArray); playerTypeDef = playerTypeRef.Resolve(); } else //this is method with no args and no response (it is not generic at all) { playerTypeRef = dynPlayerTypeRef; playerTypeDef = dynPlayerTypeDef; } var dynTestModesDef = TestFlaskAspectsModule.GetType(typeof(TestModes).FullName); var dynTestModesRef = ModuleDefinition.ImportReference(dynTestModesDef); var testModesDef = dynTestModesRef.Resolve(); MethodReference playerCtorRef; MethodReference startInvocationMethodRef; MethodReference determineTestModeMethodRef; MethodReference playMethodRef; MethodReference recordMethodRef; MethodReference callOriginalMethodRef; if (isPlayerGeneric) { playerCtorRef = ModuleDefinition.ImportReference(playerTypeDef.GetConstructors().First().MakeHostInstanceGeneric(reqResArray)); startInvocationMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "StartInvocation").MakeHostInstanceGeneric(reqResArray)); determineTestModeMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "DetermineTestMode").MakeHostInstanceGeneric(reqResArray)); playMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "Play").MakeHostInstanceGeneric(reqResArray)); recordMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "Record").MakeHostInstanceGeneric(reqResArray)); callOriginalMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "CallOriginal").MakeHostInstanceGeneric(reqResArray)); } else //this is method with no args and no response (it is not generic at all) { playerCtorRef = ModuleDefinition.ImportReference(playerTypeDef.GetConstructors().First()); startInvocationMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "StartInvocation")); determineTestModeMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "DetermineTestMode")); playMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "Play")); recordMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "Record")); callOriginalMethodRef = ModuleDefinition.ImportReference(playerTypeDef.Methods.First(m => m.Name == "CallOriginal")); } var orgMethodRef = ModuleDefinition.ImportReference(GetOrgMethodType(playableMethod.Parameters.Count, isFunc)); MethodReference orgMethodCtorRef; if (isPlayerGeneric) { GenericInstanceType orgMethodType = orgMethodRef.MakeGenericInstanceType(reqResArray); var genericOrgMethodTypeDef = orgMethodType.Resolve(); orgMethodCtorRef = ModuleDefinition.ImportReference(genericOrgMethodTypeDef.GetConstructors() .Where(c => c.Parameters.Count == 2) //(object, IntPtr) .First().MakeHostInstanceGeneric(reqResArray)); } else { orgMethodCtorRef = ModuleDefinition.ImportReference(orgMethodRef.Resolve().GetConstructors() .Where(c => c.Parameters.Count == 2) //(object, IntPtr) .First()); } MethodReference requestIdentifierCtorRef = null; if (requestIdentifier != null) { requestIdentifierCtorRef = requestIdentifier != null?ModuleDefinition.ImportReference(requestIdentifier.GetConstructors().First()) : null; } MethodReference responseIdentifierCtorRef = null; if (responseIdentifier != null) { responseIdentifierCtorRef = responseIdentifier != null?ModuleDefinition.ImportReference(responseIdentifier.GetConstructors().First()) : null; } if (isFunc) { DecorateFunc(playableMethod, originalMethod, playerTypeRef, testModesDef, responseType, requestIdentifierCtorRef, responseIdentifierCtorRef, playerCtorRef, startInvocationMethodRef, determineTestModeMethodRef, orgMethodCtorRef, callOriginalMethodRef, recordMethodRef, playMethodRef); } else { DecorateAction(playableMethod, originalMethod, playerTypeRef, testModesDef, responseType, requestIdentifierCtorRef, responseIdentifierCtorRef, playerCtorRef, startInvocationMethodRef, determineTestModeMethodRef, orgMethodCtorRef, callOriginalMethodRef, recordMethodRef, playMethodRef); } }
private static MethodDefinition GetImplementedMethodFromGenericInstanceType(this MethodDefinition self, GenericInstanceType type) { TypeDefinition typeDef = type.Resolve(); if (typeDef == null) { return(null); } foreach (MethodDefinition method in typeDef.Methods) { if (method.Name == self.Name) { if (method.HasParameters && self.HasParameters && method.Parameters.Count == self.Parameters.Count) { if (method.ReturnType.IsGenericParameter) { int parameterPosition = (method.ReturnType as GenericParameter).Position; TypeReference genericArgument; if (!type.PostionToArgument.TryGetValue(parameterPosition, out genericArgument)) { continue; } if (genericArgument.FullName != self.ReturnType.FullName) { continue; } } else if (method.ReturnType.FullName != self.ReturnType.FullName) { continue; } for (int i = 0; i < method.Parameters.Count; i++) { TypeReference parameterType = method.Parameters[i].ParameterType; if (parameterType.IsGenericParameter) { int parameterPosition = (parameterType as GenericParameter).Position; TypeReference genericArgument; if (!type.PostionToArgument.TryGetValue(parameterPosition, out genericArgument)) { continue; } if (genericArgument.FullName != self.Parameters[i].ParameterType.FullName) { continue; } } else if (parameterType.FullName != self.Parameters[i].ParameterType.FullName) { continue; } } } return(method); } } return(null); }
private static MethodDefinition GetImplementedMethodFromGenericInstanceType(this MethodDefinition self, GenericInstanceType type) { TypeDefinition typeDef = type.Resolve(); if (typeDef == null) { return null; } foreach (MethodDefinition method in typeDef.Methods) { if (method.Name == self.Name) { if (method.HasParameters && self.HasParameters && method.Parameters.Count == self.Parameters.Count) { if (method.ReturnType.IsGenericParameter) { int parameterPosition = (method.ReturnType as GenericParameter).Position; TypeReference genericArgument; if (!type.PostionToArgument.TryGetValue(parameterPosition, out genericArgument)) { continue; } if (genericArgument.FullName != self.ReturnType.FullName) { continue; } } else if (method.ReturnType.FullName != self.ReturnType.FullName) { continue; } for (int i = 0; i < method.Parameters.Count; i++) { TypeReference parameterType = method.Parameters[i].ParameterType; if (parameterType.IsGenericParameter) { int parameterPosition = (parameterType as GenericParameter).Position; TypeReference genericArgument; if (!type.PostionToArgument.TryGetValue(parameterPosition, out genericArgument)) { continue; } if (genericArgument.FullName != self.Parameters[i].ParameterType.FullName) { continue; } } else if (parameterType.FullName != self.Parameters[i].ParameterType.FullName) { continue; } } } return method; } } return null; }
TypeDefinition ExpandGenericType(GenericInstanceType genericType) { var genericName = GetGenericName(genericType); if (m_genericTypeCache.ContainsKey(genericName)) { return(m_genericTypeCache[genericName]); } var ot = genericType.Resolve(); var nt = new TypeDefinition("", genericName, TypeAttributes.Class); m_genericTypeCache[genericName] = nt; nt.BaseType = ot.BaseType; // update fields foreach (var f in ot.Fields) { var ft = f.FieldType; ft = ResolveGenericParameter(ft, genericType); var nf = new FieldDefinition(f.Name, f.Attributes, ft); nt.Fields.Add(nf); } // update Methods foreach (var m in ot.Methods) { var rt = ResolveGenericParameter(m.ReturnType, genericType); var nm = new MethodDefinition(m.Name, m.Attributes, rt); nt.Methods.Add(nm); foreach (var p in m.Parameters) { nm.Parameters.Add(new ParameterDefinition(p.Name, p.Attributes, ResolveGenericParameter(p.ParameterType, genericType))); } if (m.HasBody) { CopyTypeHelper.CopyMethodBody(m, nm); foreach (var v in nm.Body.Variables) { if (v.VariableType.ContainsGenericParameter) { v.VariableType = ResolveGenericParameter(v.VariableType, genericType); if (v.VariableType.ContainsGenericParameter || v.VariableType.IsGenericInstance) { v.VariableType = ExpandGenericType((GenericInstanceType)v.VariableType); } } } var ilp = nm.Body.GetILProcessor(); foreach (var i in nm.Body.Instructions) { if (i.Operand is MemberReference fr && fr.ContainsGenericParameter) { if (fr.DeclaringType.ContainsGenericParameter) { fr.DeclaringType = ResolveGenericParameter(fr.DeclaringType, genericType); if (fr.DeclaringType.ContainsGenericParameter || fr.DeclaringType.IsGenericInstance) { fr.DeclaringType = ExpandGenericType((GenericInstanceType)fr.DeclaringType); } } } } } } return(nt); }
private WeaveResult WeaveProperty(PropertyDefinition prop, TypeDefinition type, Dictionary <string, Tuple <MethodReference, MethodReference> > methodTable) { var columnName = prop.Name; var mapToAttribute = prop.CustomAttributes.FirstOrDefault(a => a.AttributeType.Name == "MapToAttribute"); if (mapToAttribute != null) { columnName = (string)mapToAttribute.ConstructorArguments[0].Value; } var backingField = prop.GetBackingField(); var isIndexed = prop.CustomAttributes.Any(a => a.AttributeType.Name == "IndexedAttribute"); if (isIndexed && (!_indexableTypes.Contains(prop.PropertyType.FullName))) { return(WeaveResult.Error($"{type.Name}.{prop.Name} is marked as [Indexed] which is only allowed on integral types as well as string, bool and DateTimeOffset, not on {prop.PropertyType.FullName}.")); } var isPrimaryKey = prop.CustomAttributes.Any(a => a.AttributeType.Name == "PrimaryKeyAttribute"); if (isPrimaryKey && (!_primaryKeyTypes.Contains(prop.PropertyType.FullName))) { return(WeaveResult.Error($"{type.Name}.{prop.Name} is marked as [PrimaryKey] which is only allowed on integral and string types, not on {prop.PropertyType.FullName}.")); } if (!prop.IsAutomatic()) { if (prop.PropertyType.Resolve().BaseType.IsSameAs(_realmObject)) { return(WeaveResult.Warning($"{type.Name}.{columnName} is not an automatic property but its type is a RealmObject which normally indicates a relationship.")); } return(WeaveResult.Skipped()); } if (_typeTable.ContainsKey(prop.PropertyType.FullName)) { // If the property is automatic but doesn't have a setter, we should still ignore it. if (prop.SetMethod == null) { return(WeaveResult.Skipped()); } var typeId = prop.PropertyType.FullName + (isPrimaryKey ? " unique" : string.Empty); if (!methodTable.ContainsKey(typeId)) { var getter = _realmObject.LookupMethodReference("Get" + _typeTable[prop.PropertyType.FullName] + "Value", ModuleDefinition); var setter = _realmObject.LookupMethodReference("Set" + _typeTable[prop.PropertyType.FullName] + "Value" + (isPrimaryKey ? "Unique" : string.Empty), ModuleDefinition); methodTable[typeId] = Tuple.Create(getter, setter); } ReplaceGetter(prop, columnName, methodTable[typeId].Item1); ReplaceSetter(prop, backingField, columnName, methodTable[typeId].Item2); } // treat IList and RealmList similarly but IList gets a default so is useable as standalone // IList or RealmList allows people to declare lists only of _realmObject due to the class definition else if (prop.IsIList()) { var elementType = ((GenericInstanceType)prop.PropertyType).GenericArguments.Single(); if (!elementType.Resolve().BaseType.IsSameAs(_realmObject)) { return(WeaveResult.Warning($"SKIPPING {type.Name}.{columnName} because it is an IList but its generic type is not a RealmObject subclass, so will not persist.")); } if (prop.SetMethod != null) { return(WeaveResult.Error($"{type.Name}.{columnName} has a setter but its type is a IList which only supports getters.")); } var concreteListType = new GenericInstanceType(_system_IList) { GenericArguments = { elementType } }; var listConstructor = concreteListType.Resolve().GetConstructors().Single(c => c.IsPublic && c.Parameters.Count == 0); var concreteListConstructor = listConstructor.MakeHostInstanceGeneric(elementType); // weaves list getter which also sets backing to List<T>, forcing it to accept us setting it post-init var backingDef = backingField as FieldDefinition; if (backingDef != null) { backingDef.Attributes &= ~FieldAttributes.InitOnly; // without a set; auto property has this flag we must clear } ReplaceListGetter(prop, backingField, columnName, new GenericInstanceMethod(_genericGetListValueReference) { GenericArguments = { elementType } }, ModuleDefinition.ImportReference(concreteListConstructor)); } else if (prop.PropertyType.Resolve().BaseType.IsSameAs(_realmObject)) { if (!prop.IsAutomatic()) { return(WeaveResult.Warning($"{type.Name}.{columnName} is not an automatic property but its type is a RealmObject which normally indicates a relationship.")); } // with casting in the _realmObject methods, should just work ReplaceGetter(prop, columnName, new GenericInstanceMethod(_genericGetObjectValueReference) { GenericArguments = { prop.PropertyType } }); ReplaceSetter(prop, backingField, columnName, new GenericInstanceMethod(_genericSetObjectValueReference) { GenericArguments = { prop.PropertyType } }); } else if (prop.PropertyType.FullName == "System.DateTime") { return(WeaveResult.Error($"Class '{type.Name}' field '{prop.Name}' is a DateTime which is not supported - use DateTimeOffset instead.")); } else if (prop.PropertyType.FullName == "System.Nullable`1<System.DateTime>") { return(WeaveResult.Error($"Class '{type.Name}' field '{prop.Name}' is a DateTime? which is not supported - use DateTimeOffset? instead.")); } else { return(WeaveResult.Error($"Class '{type.Name}' field '{columnName}' is a '{prop.PropertyType}' which is not yet supported.")); } var preserveAttribute = new CustomAttribute(_preserveAttributeConstructor); prop.CustomAttributes.Add(preserveAttribute); var wovenPropertyAttribute = new CustomAttribute(_wovenPropertyAttributeConstructor); prop.CustomAttributes.Add(wovenPropertyAttribute); Debug.WriteLine(string.Empty); var primaryKeyMsg = isPrimaryKey ? "[PrimaryKey]" : string.Empty; var indexedMsg = isIndexed ? "[Indexed]" : string.Empty; LogDebug($"Woven {type.Name}.{prop.Name} as a {prop.PropertyType.FullName} {primaryKeyMsg} {indexedMsg}."); return(WeaveResult.Success(prop, backingField, isPrimaryKey)); }
public void WriteDefinition(GenericInstanceType type, IMetadataCollection metadataCollection) { if (GenericsUtilities.CheckForMaximumRecursion(type)) { object[] args = new object[] { MetadataWriter.Naming.ForGenericClass(type) }; base.Writer.WriteLine("Il2CppGenericClass {0} = {{ -1, {{ NULL, NULL }}, NULL }};", args); } else { base.Writer.WriteExternForIl2CppGenericInst(type.GenericArguments); object[] objArray2 = new object[] { MetadataWriter.Naming.ForGenericClass(type), metadataCollection.GetTypeInfoIndex(type.Resolve()), MetadataWriter.Naming.ForGenericInst(type.GenericArguments), MetadataWriter.Naming.Null, MetadataWriter.Naming.Null }; base.WriteLine("Il2CppGenericClass {0} = {{ {1}, {{ &{2}, {3} }}, {4} }};", objArray2); } }
private void ReplaceContructorWithConstructorFrom(Instruction newObj) { MethodReference originalCtor = (MethodReference)newObj.Operand; GenericInstanceType originalList = (GenericInstanceType)originalCtor.DeclaringType; GenericInstanceType declaringType = new GenericInstanceType(Context.Import(_collectionReplacements[originalList.Resolve().FullName])); foreach (TypeReference argument in originalList.GenericArguments) { declaringType.GenericArguments.Add(argument); } MethodReference newCtor = new MethodReference(".ctor", Context.Import(typeof(void))); newCtor.DeclaringType = declaringType; newCtor.HasThis = true; foreach (ParameterDefinition parameter in originalCtor.Parameters) { newCtor.Parameters.Add(parameter); } newObj.Operand = newCtor; }
public static GenericInstanceType InflateType(GenericContext context, GenericInstanceType genericInstanceType) => ConstructGenericType(context, genericInstanceType.Resolve(), genericInstanceType.GenericArguments);