コード例 #1
0
ファイル: Emitter.cs プロジェクト: Ancestry/DotQL
        private TupleType TupleTypeFromNative(System.Type type)
        {
            var tupleType = new TupleType();

            // Get attributes
            foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
                tupleType.Attributes.Add(Name.FromNative(field.Name), TypeFromNative(field.FieldType));

            // Get references
            foreach (TupleReferenceAttribute r in type.GetCustomAttributes(typeof(TupleReferenceAttribute)))
                tupleType.References.Add
                (
                    Name.FromNative(r.Name),
                    new TupleReference
                    {
                        SourceAttributeNames = (from san in r.SourceAttributeNames select Name.FromNative(san)).ToArray(),
                        Target = Name.FromNative(r.Target),
                        TargetAttributeNames = (from tan in r.TargetAttributeNames select Name.FromNative(tan)).ToArray()
                    }
                );

            // Get keys
            foreach (TupleKeyAttribute k in type.GetCustomAttributes(typeof(TupleKeyAttribute)))
                tupleType.Keys.Add
                (
                    new TupleKey { AttributeNames = (from n in k.AttributeNames select Name.FromNative(n)).ToArray() }
                );

            return tupleType;
        }
コード例 #2
0
ファイル: Emitter.cs プロジェクト: Ancestry/DotQL
        private static MethodBuilder EmitTupleGetHashCode(TupleType tupleType, TypeBuilder typeBuilder, Dictionary<Name, FieldInfo> fieldsByID)
        {
            var getHashCodeMethod = typeBuilder.DefineMethod("GetHashCode", MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot, CallingConventions.HasThis, typeof(Int32), new System.Type[] { });
            var il = getHashCodeMethod.GetILGenerator();
            // result = 83
            il.Emit(OpCodes.Ldc_I4, 83);
            foreach (var keyItem in tupleType.GetKeyAttributes())
            {
                var field = fieldsByID[keyItem];

                // result ^= this.<field>.GetHashCode();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldflda, field);
                il.Emit(OpCodes.Constrained, field.FieldType);
                il.EmitCall(OpCodes.Callvirt, ReflectionUtility.ObjectGetHashCode, null);
                il.Emit(OpCodes.Xor);
            }
            il.Emit(OpCodes.Ret);
            typeBuilder.DefineMethodOverride(getHashCodeMethod, ReflectionUtility.ObjectGetHashCode);
            return getHashCodeMethod;
        }
コード例 #3
0
ファイル: Emitter.cs プロジェクト: Ancestry/DotQL
        public System.Type NativeFromTupleType(TupleType tupleType)
        {
            var typeBuilder = _module.DefineType("Tuple" + tupleType.GetHashCode(), TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.SequentialLayout | TypeAttributes.Serializable, typeof(ValueType));
            var fieldsByID = new Dictionary<Name, FieldInfo>();

            // Add attributes
            foreach (var attribute in tupleType.Attributes)
            {
                var field = typeBuilder.DefineField(attribute.Key.ToString(), attribute.Value.GetNative(this), FieldAttributes.Public);
                fieldsByID.Add(attribute.Key, field);
            }

            // Add references
            foreach (var reference in tupleType.References)
            {
                var cab =
                    new CustomAttributeBuilder
                    (
                        typeof(TupleReferenceAttribute).GetConstructor(new System.Type[] { typeof(string), typeof(string[]), typeof(string), typeof(string[]) }),
                        new object[]
                            {
                                reference.Key.ToString(),
                                (from san in reference.Value.SourceAttributeNames select san.ToString()).ToArray(),
                                reference.Value.Target.ToString(),
                                (from tan in reference.Value.TargetAttributeNames select tan.ToString()).ToArray(),
                            }
                    );
                typeBuilder.SetCustomAttribute(cab);
            }

            // Add keys
            foreach (var key in tupleType.Keys)
            {
                var cab =
                    new CustomAttributeBuilder
                    (
                        typeof(TupleKeyAttribute).GetConstructor(new System.Type[] { typeof(string[]) }),
                        new object[] { (from an in key.AttributeNames select an.ToString()).ToArray() }
                    );
                typeBuilder.SetCustomAttribute(cab);
            }

            // Add tuple attribute
            var attributeBuilder =
                new CustomAttributeBuilder
                (
                    typeof(TupleAttribute).GetConstructor(new System.Type[] { }),
                    new object[] { }
                );
            typeBuilder.SetCustomAttribute(attributeBuilder);

            // Add comparison and hash methods based on key(s)
            EmitTupleGetHashCode(tupleType, typeBuilder, fieldsByID);
            var equalityMethod = EmitTupleEquality(tupleType, typeBuilder, fieldsByID);
            EmitTupleInequality(typeBuilder, equalityMethod);
            EmitTupleEquals(typeBuilder, equalityMethod);

            // Create the type
            return typeBuilder.CreateType();
        }
コード例 #4
0
ファイル: Emitter.cs プロジェクト: Ancestry/DotQL
 private static MethodBuilder EmitTupleEquality(TupleType tupleType, TypeBuilder typeBuilder, Dictionary<Name, FieldInfo> fieldsByID)
 {
     var equalityMethod = typeBuilder.DefineMethod("op_Equality", MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, typeof(bool), new System.Type[] { typeBuilder, typeBuilder });
     var il = equalityMethod.GetILGenerator();
     var end = il.DefineLabel();
     foreach (var keyItem in tupleType.GetKeyAttributes())
     {
         var field = fieldsByID[keyItem];
         il.Emit(OpCodes.Ldarg_0);
         il.Emit(OpCodes.Ldfld, field);
         il.Emit(OpCodes.Ldarg_1);
         il.Emit(OpCodes.Ldfld, field);
         var fieldEqualityMethod = field.FieldType.GetMethod("op_Equality", new System.Type[] { field.FieldType, field.FieldType });
         if (fieldEqualityMethod != null)
             il.EmitCall(OpCodes.Call, fieldEqualityMethod, null);
         else
             il.Emit(OpCodes.Ceq);
         il.Emit(OpCodes.Dup);
         il.Emit(OpCodes.Brfalse_S, end);
         il.Emit(OpCodes.Pop);
     }
     il.Emit(OpCodes.Ldc_I4_1);	// True
     il.MarkLabel(end);
     il.Emit(OpCodes.Ret);
     return equalityMethod;
 }
コード例 #5
0
ファイル: Emitter.cs プロジェクト: Ancestry/DotQL
 public System.Type FindOrCreateNativeFromTupleType(TupleType tupleType)
 {
     System.Type nativeType;
     if (!_tupleToNative.TryGetValue(tupleType, out nativeType))
     {
         nativeType = NativeFromTupleType(tupleType);
         _tupleToNative.Add(tupleType, nativeType);
     }
     return nativeType;
 }