Exemplo n.º 1
0
        /// <summary>
        /// Get activation configuration for strategy
        /// </summary>
        /// <param name="activationType"></param>
        /// <returns></returns>
        public override TypeActivationConfiguration GetActivationConfiguration(Type activationType)
        {
            var closedType = ReflectionHelper.CreateClosedExportTypeFromRequestingType(ActivationType, activationType);

            var configuration = ActivationConfiguration.CloneToType(closedType);

            return(configuration);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get activation configuration for strategy
        /// </summary>
        /// <param name="activationType"></param>
        /// <returns></returns>
        public override TypeActivationConfiguration GetActivationConfiguration(Type activationType)
        {
            var closedType = ReflectionHelper.CreateClosedExportTypeFromRequestingType(ActivationType, activationType);

            if (closedType != null)
            {
                return(ActivationConfiguration.CloneToType(closedType));
            }

            return(base.GetActivationConfiguration(activationType));
        }
Exemplo n.º 3
0
        public void TestConfig_Success()
        {
            var config = new ActivationConfiguration()
                         .Configure <InheritedType4>(x => new InheritedType4(x.Prop1, x.Prop2, x.Prop3, x.Prop4));
            var remute   = new Remute(config);
            var instance = new InheritedType4("prop1", "prop2", "prop3", "prop4");
            var actual   = remute.With(instance, x => x.Prop1, "update");

            Assert.AreEqual("update", actual.Prop1);
            Assert.AreEqual(instance.Prop2, actual.Prop2);
            Assert.AreEqual(instance.Prop3, actual.Prop3);
            Assert.AreEqual(instance.Prop4, actual.Prop4);
        }
Exemplo n.º 4
0
        public void ConfigureByExpression_Success()
        {
            var user = new User(1, "Joe", "Doe");

            var config = new ActivationConfiguration()
                         .Configure <User>(x => new User(x.FirstName, x.LastName));

            var remute = new Remute(config);

            var actual = remute.With(user, x => x.FirstName, "Foo");

            Assert.AreEqual("Foo", actual.FirstName);
            Assert.AreEqual(user.LastName, actual.LastName);
            Assert.AreEqual(default(int), actual.Id);
        }
Exemplo n.º 5
0
        private static ConstructorInfo FindConstructor(Type type, ActivationConfiguration activationConfiguration)
        {
            if (activationConfiguration.Settings.TryGetValue(type, out ActivationSetting setting))
            {
                return(setting.Constructor);
            }

            var constructors = type.GetTypeInfo().DeclaredConstructors;

            if (constructors.Count() != 1)
            {
                throw new Exception($"Unable to find appropriate constructor of type '{type.Name}'. Consider to use {nameof(ActivationConfiguration)} parameter.");
            }

            return(constructors.Single());
        }
Exemplo n.º 6
0
        public void ConfigureByExpression_InvalidProperty_Fail()
        {
            var user = new User(1, "Joe", "Doe");

            try
            {
                var config = new ActivationConfiguration()
                             .Configure <User>(x => new User("Foo", "Bar"));
            }
            catch (Exception ex) when(ex.Message == $"Parameter \"Foo\" must be a property of '{typeof(User)}'.")
            {
                return;
            }

            Assert.Fail();
        }
Exemplo n.º 7
0
        public void ConfigureByExpression_InvalidExpression_Fail()
        {
            var user = new User(1, "Joe", "Doe");

            try
            {
                var config = new ActivationConfiguration()
                             .Configure <User>(x => x);
            }
            catch (Exception ex) when(ex.Message == $"Expression must specify constructor of '{typeof(User)}'.")
            {
                return;
            }

            Assert.Fail();
        }
Exemplo n.º 8
0
        public void ConfigureByConstructor_Success()
        {
            var user        = new User(1, "Joe", "Doe");
            var type        = user.GetType();
            var constructor = type.GetConstructor(new[] { typeof(int), typeof(string), typeof(string) });

            var config = new ActivationConfiguration()
                         .Configure(constructor);

            var remute = new Remute(config);

            var actual = remute.With(user, x => x.FirstName, "Foo");

            Assert.AreEqual("Foo", actual.FirstName);
            Assert.AreEqual(user.LastName, actual.LastName);
            Assert.AreEqual(user.Id, actual.Id);
        }
Exemplo n.º 9
0
        /// <summary>
        /// An extension method to simulate the "with" keyword from functional languages. An oversimplified description is that it creates a new instance of an immutable object with a specific value changed.
        /// </summary>
        /// <param name="expression">Expression returning the property to be mutated</param>
        /// <param name="value">The value the property is to be set to</param>
        /// <returns>A new instance of the object with the selected property set to the new value.</returns>
        public static TInstance With <TInstance, TValue>(this TInstance instance, Expression <Func <TInstance, TValue> > expression, TValue value)
            where TInstance : class
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            var activationConfiguration = new ActivationConfiguration();
            var activationContextCache  = new Dictionary <Type, ActivationContext>();

            var result = value as object;

            var instanceExpression = expression.Body;

            while (instanceExpression is MemberExpression)
            {
                var propertyExpression = instanceExpression as MemberExpression;
                instanceExpression = propertyExpression.Expression;

                var property = propertyExpression.Member as PropertyInfo;

                if (property == null)
                {
                    throw new Exception($"Unable to get property info for {propertyExpression.Member.Name} on type {typeof(TInstance).Name}. This is most likey because this was declared as a field and not a property.");
                }

                var type = property.DeclaringType;

                var activationContext = GetActivationContext(type, activationContextCache, activationConfiguration);

                var lambdaExpression   = Expression.Lambda <Func <TInstance, object> >(instanceExpression, expression.Parameters);
                var compiledExpression = lambdaExpression.Compile();
                var currentInstance    = compiledExpression.Invoke(instance);

                var arguments = ResolveActivatorArguments(activationContext.ParameterResolvers, property, currentInstance, ref result);
                result = activationContext.Activator.Invoke(arguments);
            }

            return((TInstance)result);
        }
Exemplo n.º 10
0
        public void ConfigureByConstructorAndParameters_Success()
        {
            var user        = new User(1, "Joe", "Doe");
            var type        = user.GetType();
            var constructor = type.GetConstructor(new[] { typeof(string), typeof(string) });

            var firstNameParameter = constructor.GetParameters().Single(x => x.Name == "firstNameNotMatchingPropertyName");
            var firstNameProperty  = type.GetProperty("FirstName");

            var config = new ActivationConfiguration()
                         .Configure(constructor, new Dictionary <ParameterInfo, PropertyInfo>()
            {
                [firstNameParameter] = firstNameProperty
            });

            var remute = new Remute(config);

            var actual = remute.With(user, x => x.FirstName, "Foo");

            Assert.AreEqual("Foo", actual.FirstName);
            Assert.AreEqual(user.LastName, actual.LastName);
            Assert.AreEqual(default(int), actual.Id);
        }
Exemplo n.º 11
0
        public void ConfigureByConstructorAndParameters_InvalidProperty_Fail()
        {
            var user        = new User(1, "Joe", "Doe");
            var constructor = user.GetType().GetConstructor(new[] { typeof(int), typeof(string), typeof(string) });

            var firstNameParameter = constructor.GetParameters().Single(x => x.Name == "firstName");
            var firstNameProperty  = typeof(Employee).GetProperty("FirstName");

            try
            {
                var config = new ActivationConfiguration()
                             .Configure(constructor, new Dictionary <ParameterInfo, PropertyInfo>()
                {
                    [firstNameParameter] = firstNameProperty
                });
            }
            catch (Exception ex) when(ex.Message == $"Invalid property '{firstNameProperty.Name}'. Must be a member of '{constructor.DeclaringType}'.")
            {
                return;
            }

            Assert.Fail();
        }
Exemplo n.º 12
0
        private static ActivationContext GetActivationContext(Type type, Dictionary <Type, ActivationContext> activationContextCache, ActivationConfiguration activationConfiguration)
        {
            if (activationContextCache.TryGetValue(type, out ActivationContext result))
            {
                return(result);
            }

            var constructor        = FindConstructor(type, activationConfiguration);
            var activator          = GetActivator(constructor);
            var parameterResolvers = GetParameterResolvers(type, constructor, activationConfiguration);

            result = new ActivationContext(type, activator, parameterResolvers);
            activationContextCache[type] = result;

            return(result);
        }
Exemplo n.º 13
0
        private static ParameterResolver[] GetParameterResolvers(Type type, ConstructorInfo constructor, ActivationConfiguration activationConfiguration)
        {
            var properties = type.GetTypeInfo().DeclaredProperties.ToArray();
            var parameters = constructor.GetParameters();

            var parameterResolvers = new ParameterResolver[parameters.Length];

            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter = parameters[i];
                var property  = FindProperty(type, parameter, properties, activationConfiguration);

                var expressionParameter        = Expression.Parameter(typeof(object));
                var expressionParameterConvert = Expression.Convert(expressionParameter, type);
                var expressionProperty         = Expression.Property(expressionParameterConvert, property);
                var expressionPropertyConvert  = Expression.Convert(expressionProperty, typeof(object));
                var lambda   = Expression.Lambda <Func <object, object> >(expressionPropertyConvert, expressionParameter);
                var resolver = lambda.Compile();

                var parameterResolver = new ParameterResolver(parameter, property, resolver);
                parameterResolvers[i] = parameterResolver;
            }

            return(parameterResolvers);
        }
Exemplo n.º 14
0
        private static PropertyInfo FindProperty(Type type, ParameterInfo parameter, PropertyInfo[] properties, ActivationConfiguration activationConfiguration)
        {
            if (activationConfiguration.Settings.TryGetValue(type, out ActivationSetting setting))
            {
                if (setting.Parameters.TryGetValue(parameter, out PropertyInfo property))
                {
                    return(property);
                }
            }

            properties = properties.Where(x => string.Equals(x.Name, parameter.Name, StringComparison.OrdinalIgnoreCase)).ToArray();

            if (properties.Count() != 1)
            {
                throw new Exception($"Unable to find appropriate property to use as a constructor parameter '{parameter.Name}'. Type '{type.Name}'. Consider to use {nameof(ActivationConfiguration)} parameter.");
            }

            return(properties.Single());
        }