/// <summary>
        /// Returns whether the type reference is of a type that can be replaced by ObservableCollection{T}.
        /// </summary>
        /// <param name="typeReference">The typeReference to check.</param>
        /// <param name="weavingContext">The weavingContext to use..</param>
        /// <returns>True when the type is a type that can be replaced by one of the interfaces of ObservableCollection{T}", false otherwise.</returns>
        public static bool IsReplaceableCollection(this TypeReference typeReference, WeavingContext weavingContext)
        {
            if (typeReference is null)
            {
                throw new ArgumentNullException(nameof(typeReference));
            }

            if (weavingContext is null)
            {
                throw new ArgumentNullException(nameof(weavingContext));
            }

            var module = typeReference.Module;

            var observableCollectionTypes = new TypeDefinition[]
            {
                weavingContext.CortexNetTypesObservableDictionary.Resolve(),
                weavingContext.CortexNetTypesObservableSet.Resolve(),
                weavingContext.CortexNetTypesObservableCollection.Resolve(),
            };

            var typeToCheck       = typeReference.Resolve();
            var interfacesToCheck = typeToCheck.Interfaces.OrderBy(x => x.InterfaceType.FullName).ToList();

            foreach (var interfaceImplementation in observableCollectionTypes.SelectMany(x => x.Interfaces).OrderBy(x => x.InterfaceType.FullName))
            {
                foreach (var interfaceImplementationToCheck in interfacesToCheck)
                {
                    var compare = string.Compare(interfaceImplementation.InterfaceType.FullName, interfaceImplementationToCheck.InterfaceType.FullName, StringComparison.InvariantCulture);

                    if (compare == 0)
                    {
                        return(true);
                    }
                    else if (compare > 0)
                    {
                        break;
                    }
                }
            }

            return(false);
        }
Example #2
0
        /// <summary>
        /// Executes the <see cref="ModuleWeaver"/>.
        /// </summary>
        public override void Execute()
        {
            WeavingContext weavingContext = null;

            try
            {
                weavingContext =
                    this.ModuleDefinition.AssemblyReferences.Any(x => x.Name == "Cortex.Net.Blazor") ?
                    new BlazorWeavingContext(this) :
                    new WeavingContext(this);
#pragma warning disable CA1031 // Do not catch general exception types
            }
            catch
#pragma warning restore CA1031 // Do not catch general exception types
            {
                this.WriteWarning(Resources.CannotLoadTypes);
                return;
            }

            var reactiveObjectInterfaceWeaver = new ReactiveObjectInterfaceWeaver(this, weavingContext);
            var enumerableWeaver = new EnumerableInterfaceWeaver(this, reactiveObjectInterfaceWeaver, weavingContext);

            var actionWeaver = new ActionWeaver(this, reactiveObjectInterfaceWeaver, weavingContext);

            var observableWeaver = new ObservableWeaver(this, enumerableWeaver, reactiveObjectInterfaceWeaver, weavingContext);
            var computedWeaver   = new ComputedWeaver(this, reactiveObjectInterfaceWeaver, weavingContext);

            actionWeaver.Execute();
            observableWeaver.Execute();
            computedWeaver.Execute();

            if (this.ModuleDefinition.AssemblyReferences.Any(x => x.Name == "Cortex.Net.Blazor"))
            {
                var blazorObserverWeaver = new BlazorObserverWeaver(this, reactiveObjectInterfaceWeaver, (BlazorWeavingContext)weavingContext);
                blazorObserverWeaver.Execute();
            }

            reactiveObjectInterfaceWeaver.Execute();
        }
Example #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ActionWeaver"/> class.
 /// </summary>
 /// <param name="parentWeaver">A reference to the Parent Cortex.Net weaver.</param>
 /// <param name="processorQueue">The queue to add ILProcessor actions to.</param>
 /// <param name="weavingContext">The resolved types necessary by this weaver.</param>
 /// <exception cref="ArgumentNullException">When any of the arguments is null.</exception>
 public ActionWeaver(ModuleWeaver parentWeaver, ISharedStateAssignmentILProcessorQueue processorQueue, WeavingContext weavingContext)
 {
     this.parentWeaver   = parentWeaver ?? throw new ArgumentNullException(nameof(parentWeaver));
     this.processorQueue = processorQueue ?? throw new ArgumentNullException(nameof(processorQueue));
     this.weavingContext = weavingContext ?? throw new ArgumentNullException(nameof(weavingContext));
 }
Example #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ComputedWeaver"/> class.
 /// </summary>
 /// <param name="parentWeaver">A reference to the Parent Cortex.Net weaver.</param>
 /// <param name="processorQueue">The queue to add ILProcessor actions to.</param>
 /// <exception cref="ArgumentNullException">When any of the arguments is null.</exception>
 /// <param name="weavingContext">The resolved types necessary by this weaver.</param>
 public ComputedWeaver(ModuleWeaver parentWeaver, ISharedStateAssignmentILProcessorQueue processorQueue, WeavingContext weavingContext)
     : base(parentWeaver, processorQueue, weavingContext)
 {
 }
        /// <summary>
        /// Creates a field.
        /// </summary>
        /// <param name="classType">The type reference of the class.</param>
        /// <param name="fieldType">The type reference of the Field.</param>
        /// <param name="name">The name of the field.</param>
        /// <param name="weavingContext">The weaving context.</param>
        /// <param name="fieldAttributes">The field Atrributes.</param>
        /// <returns>The Field definition. It has already been added to the class type.</returns>
        public static FieldDefinition CreateField(this TypeDefinition classType, TypeReference fieldType, string name, WeavingContext weavingContext, FieldAttributes fieldAttributes = FieldAttributes.Private)
        {
            if (classType is null)
            {
                throw new ArgumentNullException(nameof(classType));
            }

            if (fieldType is null)
            {
                throw new ArgumentNullException(nameof(fieldType));
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name));
            }

            if (weavingContext is null)
            {
                throw new ArgumentNullException(nameof(weavingContext));
            }

            var field = new FieldDefinition(name, fieldAttributes, fieldType);

            // Add compiler generated attribute.
            var ctor    = weavingContext.SystemRuntimeCompilerServicesCompilerGeneratedAttribute.Resolve().Methods.Single(x => x.IsConstructor && !x.IsStatic);
            var ctorRef = classType.Module.ImportReference(ctor);
            var compilerGeneratedAttribute = new CustomAttribute(ctorRef, new byte[] { 01, 00, 00, 00 });

            field.CustomAttributes.Add(compilerGeneratedAttribute);

            // Add Debugger broswable attribute.
            ctor    = weavingContext.SystemDiagnosticsDebuggerBrowsableAttribute.Resolve().Methods.Single(x => x.IsConstructor && !x.IsStatic);
            ctorRef = classType.Module.ImportReference(ctor);
            var debuggerBrowsableAttribute = new CustomAttribute(ctorRef, new byte[] { 01, 00, 00, 00, 00, 00, 00, 00 });

            field.CustomAttributes.Add(debuggerBrowsableAttribute);

            classType.Fields.Add(field);
            return(field);
        }
 /// <summary>
 /// Creates a backing field for a property.
 /// </summary>
 /// <param name="classType">The type reference of the class.</param>
 /// <param name="fieldType">The type reference of the Field.</param>
 /// <param name="name">The name of the Property.</param>
 /// <param name="weavingContext">The weaving context.</param>
 /// <returns>The Field definition. It has already been added to the class type.</returns>
 public static FieldDefinition CreateBackingField(this TypeDefinition classType, TypeReference fieldType, string name, WeavingContext weavingContext)
 {
     return(CreateField(classType, fieldType, $"<{name}>k__BackingField", weavingContext));
 }
        /// <summary>
        /// Creates a default getter for a property.
        /// </summary>
        /// <param name="classType">The type reference of the class.</param>
        /// <param name="backingField">A reference to the backing field.</param>
        /// <param name="name">The name of the property.</param>
        /// <param name="weavingContext">The weaving context.</param>
        /// <param name="methodAttributes">The methodAttributes for this getter. Default value is MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName.</param>
        /// <param name="emitAction">Extra emit action after default setter.</param>
        /// <returns>A method definition. The method is already added to the <paramref name="classType"/>.</returns>
        public static MethodDefinition CreateDefaultSetter(
            this TypeDefinition classType,
            FieldDefinition backingField,
            string name,
            WeavingContext weavingContext,
            MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName,
            Action <ILProcessor> emitAction   = null)
        {
            if (classType is null)
            {
                throw new ArgumentNullException(nameof(classType));
            }

            if (backingField is null)
            {
                throw new ArgumentNullException(nameof(backingField));
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name));
            }

            if (weavingContext is null)
            {
                throw new ArgumentNullException(nameof(weavingContext));
            }

            var moduleDefinition = classType.Module;

            var voidType = moduleDefinition.TypeSystem.Void;

            var splittedName = name.Split('.');

            if (splittedName.Length > 1)
            {
                name  = string.Join(".", splittedName.Take(splittedName.Length - 1));
                name += $".set_{splittedName.Last()}";
            }

            var method = new MethodDefinition(name, methodAttributes, voidType);

            method.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, backingField.FieldType));

            // Add compiler generated attribute.
            var ctor    = weavingContext.SystemRuntimeCompilerServicesCompilerGeneratedAttribute.Resolve().Methods.Single(x => x.IsConstructor && !x.IsStatic);
            var ctorRef = classType.Module.ImportReference(ctor);
            var compilerGeneratedAttribute = new CustomAttribute(ctorRef, new byte[] { 01, 00, 00, 00 });

            method.CustomAttributes.Add(compilerGeneratedAttribute);

            // add method to class type.
            classType.Methods.Add(method);

            var backingFieldReference = moduleDefinition.ImportReference(backingField);

            // generate method body.
            var processor = method.Body.GetILProcessor();

            processor.Emit(OpCodes.Ldarg_0);
            processor.Emit(OpCodes.Ldarg_1);
            processor.Emit(OpCodes.Stfld, backingFieldReference);

            // execute processor action before return.
            emitAction?.Invoke(processor);

            processor.Emit(OpCodes.Ret);

            return(method);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ReactiveObjectInterfaceWeaver"/> class.
 /// </summary>
 /// <param name="parentWeaver">The parent weaver.</param>
 /// <param name="weavingContext">The resolved types necessary by this weaver.</param>
 public ReactiveObjectInterfaceWeaver(ModuleWeaver parentWeaver, WeavingContext weavingContext)
 {
     this.parentWeaver   = parentWeaver ?? throw new ArgumentNullException(nameof(parentWeaver));
     this.weavingContext = weavingContext ?? throw new ArgumentNullException(nameof(weavingContext));
 }
Example #9
0
        /// <summary>
        /// Gets the Action type for the private field that is added to the class for the private method.
        /// </summary>
        /// <param name="methodDefinition">The method definition for the action.</param>
        /// <param name="weavingContext">The weaving context.</param>
        /// <returns>A type reference.</returns>
        public static TypeReference GetActionType(this MethodDefinition methodDefinition, WeavingContext weavingContext)
        {
            if (methodDefinition is null)
            {
                throw new ArgumentNullException(nameof(methodDefinition));
            }

            if (weavingContext is null)
            {
                throw new ArgumentNullException(nameof(weavingContext));
            }

            var moduleDefinition = methodDefinition.Module;

            if (methodDefinition.Parameters == null || !methodDefinition.Parameters.Any())
            {
                return(moduleDefinition.ImportReference(weavingContext.SystemAction[0]));
            }

            TypeReference genericActionType;

            switch (methodDefinition.Parameters.Count)
            {
            case int i when i > 0 && i <= 16:
                genericActionType = moduleDefinition.ImportReference(weavingContext.SystemAction[i]);
                break;

            default:
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.MoreThan16Parameters, methodDefinition.Name));
            }

            var instance = new GenericInstanceType(genericActionType);

            foreach (var parameter in methodDefinition.Parameters)
            {
                instance.GenericArguments.Add(parameter.ParameterType);
            }

            return(instance);
        }
Example #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ObservableWeaver"/> class.
 /// </summary>
 /// <param name="parentWeaver">A reference to the Parent Cortex.Net weaver.</param>
 /// <param name="enumerableInterfaceWeaver">An implementation of <see cref="IEnumerableInterfaceWeaver" />.</param>
 /// <param name="processorQueue">The queue to add ILProcessor actions to.</param>
 /// <param name="weavingContext">The resolved types necessary by this weaver.</param>
 /// <exception cref="ArgumentNullException">When any of the arguments is null.</exception>
 public ObservableWeaver(ModuleWeaver parentWeaver, IEnumerableInterfaceWeaver enumerableInterfaceWeaver, ISharedStateAssignmentILProcessorQueue processorQueue, WeavingContext weavingContext)
     : base(parentWeaver, processorQueue, weavingContext)
 {
     this.enumerableInterfaceWeaver = enumerableInterfaceWeaver ?? throw new ArgumentNullException(nameof(enumerableInterfaceWeaver));
 }
Example #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ObservableObjectWeaverBase"/> class.
 /// </summary>
 /// <param name="parentWeaver">The parent weaver.</param>
 /// <param name="processorQueue">The processor queue to add delegates to.</param>
 /// <param name="weavingContext">The resolved types necessary by this weaver.</param>
 protected ObservableObjectWeaverBase(ModuleWeaver parentWeaver, ISharedStateAssignmentILProcessorQueue processorQueue, WeavingContext weavingContext)
 {
     this.ParentWeaver   = parentWeaver ?? throw new ArgumentNullException(nameof(parentWeaver));
     this.ProcessorQueue = processorQueue ?? throw new ArgumentNullException(nameof(processorQueue));
     this.WeavingContext = weavingContext ?? throw new ArgumentNullException(nameof(weavingContext));
 }